What Z80 development tools do you use? What books?
Hi. I've been meaning to do it for over 25 years, but.. better late than never :) I'm starting to learn machine code and am trying to get a development environment set up. i starting off using what I was used to from the old days, Zeus Assembler, then moved onto the assembler in BASin which is pretty good. Also using a program called Z80 PC Assembler or z80asm which is pretty good cos it generates .tzx files but I can't get this program to work on it..
(nicked from Johnathan Cauldwell's How to write ZX Spectrum Games)
It doesn't like the defb.. think you have to use DB.. and doesn't like the last line at all... any ideas on how to get this working?
So I'd be interested to know what you 'pros' use for Spectrum machine code development? What's the best way? And also... what are the best books for learning Z80... I'm currently using Toni Baker's Book. Any advice much appreciated.
ld a,2 ; upper screen
call 5633 ; open channel
loop ld de,string ; address of string
ld bc,eostr-string ; length of string to print
call 8252 ; print our string
jp loop ; repeat until screen is full
string defb 'xyzzy is cool'
eostr equ $
(nicked from Johnathan Cauldwell's How to write ZX Spectrum Games)
It doesn't like the defb.. think you have to use DB.. and doesn't like the last line at all... any ideas on how to get this working?
So I'd be interested to know what you 'pros' use for Spectrum machine code development? What's the best way? And also... what are the best books for learning Z80... I'm currently using Toni Baker's Book. Any advice much appreciated.
Post edited by xyzzy on
We have cave!
WWW
WWW
Comments
Message:
DB " Hello World "
I started with the Zeus Assembler but found that the cross-assemblers e.g. Pasmo and z80asm are more convenient. My favourite is the Telemark Cross Assembler which uses the same directives on a variety of 8-bit chips and can be used for machines like the Sinclair MK14, C64, BBC, ZX Spectrum etc.
http://home.comcast.net/~tasm/
G.
Ah, I almost forgot: you should probably announce a string with "DEFM" (message) instead of "DEFB" (bytes).
One or two things I would advise:
1. Forget about decimal. You really don't want to be thinking in decimal while writing in asm, try to think in hex. Personally, I think the world should abandon base 10 and adopt base 16 instead, it would make my life far easier :-) Actually, binary is what you need to think in a lot of the time, but hex and binary go together well, but decimal and binary don't. It's easy to convert numbers from hex to binary and back again in your head, it's much more difficult with base 10...and you really have to be thinking how the machine "thinks". So although it's not critical that you "CALL 5633" instead of "CALL 0x1601" it's worth getting into the habit.
2. Things like DEFB and EQU can sometimes be a bit assembler-specific. What you write would be fine on, say, sjasmplus. This is may be where you're running into trouble - the assembler you're using may not let you DEFB a string. (In sjasmplus you can also do something like:
to make a NULL-terminated C string.
Incidentally, here's another way of printing a string, this time a NULL-terminated string (aka a C string, as in how the C language represents strings). That is, a string ending with a byte 0x00 to say it's ended:
I use this example because there is something you'll see a lot in other assembly listings, but may confuse you as you've only just started out.
See the ld a, (hl) then followed by "and a" and "ret z". The "and a" and "ret z" basically make you return when the byte you just fetched from memory is 0x00. Now why not use CP 0 / RET Z to do the same thing?
Well, CP 0 / RET Z would also work just fine. But CP 0 requires 2 bytes and requires 7 T-states. AND A requires 1 byte and takes 4 T-states. What AND A does is does a bitwise logical AND of the accumulator against itself. If you look in the Z80 manual, you'll find if the result of an AND operation is zero, the zero flag gets set. So effectively it means you can use AND A to test whether A is zero or non zero faster and with less space than the obvious instruction of CP 0.
As I said, I mention this now because it's such a commonly done thing that you're going to see it almost straight away if you are looking at someone else's code.
There is also another extremely common trick with using one of the logical operators with the accumulator. That is using XOR A - instead of LD A, 0. If you exclusive or something against itself, you'll always get the result zero. Again, XOR A takes 1 byte and 4 T-states, instead of 2 bytes and 7 T-states for LD A, 0.
One resource that you (eventually) won't be able to live without is the Zilog Z80 User Manual. You can download the PDF from Zilog (unfortunately they recently changed their website so that it now shows all the nice shiny marketing stuff, but it's almost impossible to navigate to the actual documentation... so here's a direct link)
http://www.zilog.com/docs/z80/um0080.pdf
Here's a thread related to Spin assembler directives and features: http://www.worldofspectrum.org/forums/showthread.php?t=27451.
Try the above...
(1) I actually keep a collection of assemblers... That way, if a source file won't compile on one assembler, it might on another...
(2) I love EmuZwin, Spin and z80VisualAssembler (Russian, i think), for their simple IDE type interfaces... Much as I love Spin, I have to confess to finding the Russian EmuZwin most helpful for beginners like myself, due to its Help button that actually allows you to point and click on Assembly commands from a list in an intuitive way... I don't know if the new EmuZwinGL incorporates the same assembler, but Im still using the old version and would highly recommend it...
(3) I find that by themselves, assemblers are ugly things, quite offensive to the sensibilities of newcomers like myself - But after a little tweaking and work, an IDE here, a batch file there, almost any assembler can be "pleasant" to work with if tied to something that your already comfortable using - For me, it comes down mainly to the interface you chose to work with... For instance, The Programmers Notepad or ConTEXT both allow colour highlighting of syntax, input style Im already used to and easy cutting and pasting, along with push button macros for compiling your code and executing the results. These things, while not strictly assembler related, do make a big difference to the workflow and your motivation when writing code...
(4) For some reason, I never got into native speccy assemblers (Zeus?)... It never made sense to me to restrict your workflow to the confines of the speccy if you had a PC available that would allow multitasking, cut and paste and faster processing... Somehow I also 'feel' more secure with playing around PC ascii text files, that are at least fully portable, than relying on having my source code in a format that exists only within the limitations of the speccy itself...
...I guess, at the end of the day, it all comes to down to personal preferrences... Im enjoying reading about what you guys are used to using and why... its quite an eye-opener...
Why has no-one written a code beautifier for z80 assembly?...
You know, the sort of tool that could examine a source file and maybe do something useful like,
- optimise repetitive routines
- standardise all those wierd and wonderful macros that are particular to each and every assembler...
- maybe allow you to convert your assembly from one format to another (eg: from EmuZwin to something that would work on Spin, or TASM to PASMO, or SJASM, etc)?
We have convertors for taking binary files and turning them into assembly (you know the ones, that spit out lots of DB, or DW entries - Iv written them myself and there are plenty out there) in various forms (eg: some specialising in picture files), but I think it might be useful to have something that converts between various different assembly macro standards... Whats you thoughts?...
(And "no", I ain't writing it - Im stuggling enough right now just trying to learn Ruby in the hopes of writing something simple but unrelated)...
Does anyone know why z80asm doesn't like the line eostr equ $ or what the equivalent would be?
I think Toni Baker's (it that a man or a woman) book Mastering Maching Code on Your ZX Spectrum is pretty good.. I've got to chapter 6 :smile: It helps to take it slow and re-read it to get your head round the concepts :-?
WWW
Never used z80asm before but I've seen some assemblers use 'equ *' for the same purpose.
"* in asm.c: @ is a special 'label' indicating the current PC"
Hmmm... it's been a long time since I last looked into it, but z80asm didn't support EQU, and maybe it still doesn't support it, so instead of "constant EQU value" you must use "DEFC constant = value".
Anyway, I don't know what's the use of that line. If $ means the current position, wouldn't it be enough setting eostr as a label?
string defm 'xyzzy is cool'
eostr
No, no, no!
Some programmers prefer hex, some don't. I still think in base ten, and never had any trouble doing binary/denary conversions in the 25 odd years I've been programming. As far as I'm concerned, hex is an abomination, a crime against nature. It's a number base devised by those evil Commodore types as they sit around icons of breadbins, sacrificing ferrets, chanting assembly language mnemonics and generally plotting to take over the world.
Seriously, which base you prefer is very much a personal thing. Go with whichever number base you want. There's no need to learn hex if you don't want to, it's entirely up to you which base you program in - if hex just happens to make it easier for you, then go with it.
Egghead Website
Arcade Game Designer
My itch.io page
I have written six games for Spectrum and still didn't learn hexadecimal numbers well.
When I see e.g. number #ABCD I have no idea what it is, is it big or small, what part of memory does it belong to. I need to use calculator to get the value.
Maybe my problem is that I should think of it as of number "ei bi si di" and not try to convert it to decimal. Just learn all key values (start of screen memory, attributes) and compare my numbers to these numbers.
However in my code I often use for example
LD HL,64*256+128
when I need to combine two registers into one. Maybe a bad habit, but it works for me :)
Incidentally, in Spin there's one white pixel in the top right-hand corner in fullscreen mode.. catches the eye a bit.. anyone know who to get rid of that?
I'm gonna check out them other compilers...
WWW
Because you need to load hl with the string address AFTER you open the channel. You might want to tag a null terminator byte to the end of your string too.
Egghead Website
Arcade Game Designer
My itch.io page
You're not talking about the same z80asm... it's a more recent assembler that uses the same name. It would be helpful if tool authors would do a brief name search on google to see if the name was already taken.
z80asm is also the name of the assembler that comes with z88dk and it is available as an independent package as well. It is not to be confused with this other z80asm the OP is talking about.
I use z80asm (as a part of z88dk) for my asm needs of course :-) It is one of only a couple of available z80 assemblers that integrates a linker which makes it possible to easily share code. This is essential for high level language compilers, one of which (a C compiler) comes as part of the z88dk package. The most prolific modern day spectrum programmers (with the exception of the mojon twins) use their own privately held code for their projects. z88dk, with z80asm, is the other approach where code is publicly published and is available for use in projects. It is the linking capability of z80asm that makes this possible. z80asm does have its quirks, moreso than most z80 assemblers, and it is missing the notion of multiple code and data segments to automatically target > 64k machines.
Write games in C using Z88DK and SP1
Ah that works :) when you say a null terminator byte at end of string you mean..
str defm "print - damnyou",""
or
str defm "print - damnyou",0
or what exactly?
WWW
*Heaves a huge sigh of relief*
I thought something was wrong with me when books and people told me to think in hex, and I struggled with it. No matter how much I try I still end up opening a calc and doing hex to denary and vice versa. The problem I think is that hex to binary and vice-versa is relatively easy but hex to denary and vice-versa is a bit more difficult (at least for me!).
Bytes:Chuntey - Spectrum tech blog.
binary for bitwise operations
decimal for things that make sense in decimal (counts, etc.)
hex for things that make sense in hex (dealing with nibbles, etc.)
labels for everything else (black for 0, blue for 1, when dealing with colours, etc.)
I would say that it depends not only on programmer choice, but situation. Sometimes (because humans are used to counting in decimal), base 10 is more readable for most people -- if you want a loop to go around, say, 15 times, it could be better to use 15 rather than 0F. Other times, though, I find hex can be easier, such as working with binary patterns or flags because hex breaks nicely into four-bit pieces for its digits.
Also, many non-round decimal numbers that crop up all the time (e.g. where video-RAM starts on the Spectrum) turns out to be a very round number in binary/hex. Sometimes, this 'roundness' can help in working with those numbers.
It may be considered by some to be bad programming practice to mix number bases, but, for me, I think programming (and readability) can be enhanced by using different number bases in different situations.
Another example of using another number base -- where I've found myself using binary directly -- is Spectrum attributes because the bit pattern itself is so easy to 'read' as what flash/bright/paper/ink it is straight from the binary.
http://sgate.iit.bme.hu/patai/publications/z80guide/index.htm
I have to say that I do pretty much the same.
I do tend to use HEX constantly when dealing with 16-bit numbers though - as I find it makes the high/low byte order much clearer when reading the source-code.
An example for the OP:
Need to use version 2.20 or above though, as there were some issues with previous versions.
The only books I have in hard copy are the Basic Manual (has an index of op-codes) and Introducing Spectrum Machine Code by Iain Sinclair (has an alphabetical index of assembly instructions).
You could try my tutorial (see my sig below) . . .
I must admit I second that. I've tried out the various assemblers but to be honest at this stage I'm looking to keep things as simple as possible and anything non-windows based where I have to use a command line makes me run a mile in the opposite direction. Learning Z80 assembly is difficult enough! Spin has a fairly user-friendly assembler and you can test your code right away, and it won't bugger it up if it crashes (which happens a lot) :roll:
Well, I wrote my first program.. prints the numbers 1-20 on the screen.. whoopee do :smile:
Yay! the sense of achievement, even getting a pathetic little program like this, to work in 'real machine code' is wonderful :)
My second program, Multicolour Border, is interesting...
Interestingly when you dis-assemble this because there's a DEF* statement in the middle of the program it comes up with gibberish after this point. Any way around this?
Also looping HL down from 60,000, each loop changing the border colour 7 times, I'm loading H then L into A and AND A'ing it to check the status of the zero flag, which seems a bit kludgy.. any suggestions for a more elegant approach to looping 60,000 times?
It's mentally fast though, doing 60000*7 border colour change loops in 5 seconds.. woow, the power of machine code :-o I doubt my Pentium Dual-Core processor could do it faster :rolleyes:
Finally, when 'opening up' the screen ready for printing, is there any difference between this..
and this...
?
WWW
Personally I prefer to use 255 as the terminator which doesn't prevent you from using 0 as the argument for Ink/Paper/At control characters.
sure.. in which case you'd just use CP 255 / RET Z instead of AND A / RET Z I presume.
WWW
As you're just starting out you should get into the early habit of looking for redundancy in your code. As your projects become more and more involved you will find yourself wishing the Z80 ran a lot faster than 3.5mhz! Shaving clock cycles (the time the Z80 spends processing each instruction) from within your code should become second nature - and it's better to get into the habit now!
Very quickly looking at your code there are a few areas (marked in red) where some cycles could be saved:
I've never used the ROM to do any screen printing stuff - so the LD B,0 *might* be redundant too, providing the call to 6683 doesn't destroy the BC pair? If so, then you could move the LD B,0 outside of the main loop, and pre-load it with the (already) zeroed A from above. Sinclair ROM aficionados will put you right on that one! ;)
I suppose at the moment machine code seems to be just so ultra-fast? Perhaps even too fast? But, as I mentioned above, it won't be long before you wish the Z80 was *much* faster! What, you don't believe me?! Just wait and see! ;) ;)
Getting into the habit of looking for redundant code early on in your Z80 career makes lots of sense! :p