What Z80 development tools do you use? What books?

edited January 2010 in Development
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..
       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
«1

Comments

  • edited December 2009
    Try using DB and double quotes around the text. e.g.

    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.
  • edited December 2009
    I tried several books about MC and ended up with Toni Baker, tried several assemblers (a.o. Zeus) and ended up writing my own. There can be joy in programming MC!
    Ah, I almost forgot: you should probably announce a string with "DEFM" (message) instead of "DEFB" (bytes).
  • edited December 2009
    I use sjasmplus as a cross assembly tool. Others like to use pasmo. Some others may use the z88dk's assembler (which has a linker, making it easier to build/use libraries).

    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:
    foo    DEFB "Foo bar baz",0
    

    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:
    ; Enter with HL as the address of the string
       ld a, 2
       call 0x1601   ; set the channel
    .loop
       ld a, (hl)    ; fetch char to print
       and a         ; is A zero?
       ret z         ; return if it is
       rst 0x10      ; print the char
       inc hl        ; next byte
       jr .loop
    

    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
  • edited December 2009
    I've been using Spin (v0.666) with its built-in assembler.

    Here's a thread related to Spin assembler directives and features: http://www.worldofspectrum.org/forums/showthread.php?t=27451.
  • edited December 2009
    xyzzy wrote: »
    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..
     
           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 [B]defm[/B] 'xyzzy is cool'
    eostr  equ $
    

    Try the above...
  • edited December 2009
    Im going to sound like a complete newbie here, cos z80 is not my strong point but...
    (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...
  • edited December 2009
    ...Here is a thought,

    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)...
  • edited December 2009
    Thanks for the feedback.. I'll download 'em and 'em all out.. Spin looks promising to begin with, only it runs dead slow on my system :-( I was getting comfortable with the assembler in BASin but you can't seem to toggle between insert and overwrite mode when editing.. it's permanently stuck in overwrite which makes editing a pain. I've just been using notepad to edit before loading that into BASin's assembler, which isn't ideal.

    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 :-?
    We have cave!
    WWW
  • edited December 2009
    xyzzy wrote: »
    Does anyone know why z80asm doesn't like the line eostr equ $ or what the equivalent would be?

    Never used z80asm before but I've seen some assemblers use 'equ *' for the same purpose.
  • edited December 2009
    But I also see this in z80asm's changelog:
    "* in asm.c: @ is a special 'label' indicating the current PC"
  • edited December 2009
    xyzzy wrote: »
    Does anyone know why z80asm doesn't like the line eostr equ $ or what the equivalent would be?

    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
  • edited December 2009
    Winston wrote: »
    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.

    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.
    Still supporting Multi-Platform Arcade Game Designer, currently working on AGD 5. I am NOT on Twitter.
    Egghead Website
    Arcade Game Designer
    My itch.io page
  • edited December 2009
    Some programmers prefer hex, some don't.

    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 :)
  • edited December 2009
    Winston wrote: »
    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:
    ; Enter with HL as the address of the string
       ld a, 2
       call 0x1601   ; set the channel
    .loop
       ld a, (hl)    ; fetch char to print
       and a         ; is A zero?
       ret z         ; return if it is
       rst 0x10          ; print the char
       inc hl        ; next byte
       jr .loop
    
    ... hmm so why don't this work? (in Spin)
    ; Enter with HL as the address of the string
       ld hl,str
       ld a, 2
       call 1601h   ; set the channel
    loop
       ld a, (hl)    ; fetch char to print
       and a         ; is A zero?
       ret z         ; return if it is
       rst 10h  ; print the char
       inc hl        ; next byte
       jr loop
    
    
    str defm "print - damnyou"
    

    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...
    We have cave!
    WWW
  • edited December 2009
    xyzzy wrote: »
    ... hmm so why don't this work? (in Spin)
    ; Enter with HL as the address of the string
       ld hl,str
       ld a, 2
       call 1601h   ; set the channel
    loop
       ld a, (hl)    ; fetch char to print
       and a         ; is A zero?
       ret z         ; return if it is
       rst 10h  ; print the char
       inc hl        ; next byte
       jr loop
    
    
    str defm "print - damnyou"
    

    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.
    Still supporting Multi-Platform Arcade Game Designer, currently working on AGD 5. I am NOT on Twitter.
    Egghead Website
    Arcade Game Designer
    My itch.io page
  • edited December 2009
    Metalbrain wrote: »
    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".

    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.
  • edited December 2009
    jonathan wrote: »
    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.

    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?
    We have cave!
    WWW
  • edited December 2009
    Metalbrain wrote: »
    ...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
    Assemblers often want a label to be followed by an Opcode or pseudo Opcode. Like in this silly example:
    string DEFM 'xxxxx'
    eostr  NOP
    
  • edited December 2009
    jonathan wrote: »
    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.

    *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!).
  • edited December 2009
    Although I use Pasmo, I should really switch to z80asm (part of z88dk). Pasmo handles more than a few things in a non-standard way which means the code will not compile correctly on other assemblers. I'm sure the question of number notation was asked quite recently in another thread but my personal preference is for:

    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.)
  • edited December 2009
    Arjun wrote: »
    ....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!).
    For me hex is not difficult but honestly I hardly find a purpose for it since I left the days of programming on paper and then poking the numbers by hand. Bitwise notations remained usefull and labels are a blessing....
  • edited December 2009
    Arjun wrote: »
    *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!).

    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.
  • edited December 2009
    Today I accidently hit upon a Z80 MC guide of which I enjoyed the spirit very much:
    http://sgate.iit.bme.hu/patai/publications/z80guide/index.htm
  • edited December 2009
    aowen wrote: »
    ...

    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 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:
    ld hl,12345   ;Not immediatly clear which byte goes to H and which to L
    ld hl,&3039   ;Much clearer!
    
  • edited December 2009
    FWIW, I use the GNU binutils suite, giving full make, assemble, link, library support etc. The dogs danglies.

    Need to use version 2.20 or above though, as there were some issues with previous versions.
  • edited January 2010
    Another vote for Spin 0.666 here.
    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) . . .
  • edited January 2010
    bigjon wrote: »
    Another vote for Spin 0.666 here.
    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:
    ;Prints numbers 1-20 to the screen
    
    		xor a
    		ld (5C3Ch),a    ;open screen for printing
    ;
    		ld a,0
    loop		inc a
    		ld b,0		;
    		ld c,a		;load bc with a
    		push af		;push a out of way for a bit
    		call 6683	;print bc
    		ld a,13		;
    		rst 10h		;print Return
    		pop af		;get back a
    		cp 20		;a-20=...
    		ret z		;exit if 20-20=0
    		jr loop		;next number!
    
    

    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...
    ;   MULTICOLOUR BORDER with kludy long loop?
    
    	xor a
    	ld (5C3Ch),a
    ;	
    	call WrtMsg
    defm 16,4,17,2,22,11,7,"Hi there, partner!",0
    ;
    	ld hl,60000
    ;
    loop2	ld a,8
    ;
    loop	dec a
    	out (254),a
    	and a	
    	jr nz,loop
    ;
    	dec hl
    	ld a,h
    	and a		
    	jr nz,loop2	
    	ld a,l
    	and a
    	jr nz,loop2
    	ret 
    ;
    ;
    ;
    WrtMsg	pop hl
    	ld a,(hl)
    	inc hl
    	push hl
    	and a
    	ret z
    	rst 10h
    	jr WrtMsg
    

    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..
    xor a              ;LET a=0
    ld (5C3Ch),a       ;system variable 'TVFLAG'
    

    and this...
    ld a,2              
    call 5633    ;as in Johnathan Cauldwell's book       
    
    

    ?
    We have cave!
    WWW
  • edited January 2010
    xyzzy wrote: »
    defm 16,4,17,2,22,11,7,"Hi there, partner!",0

    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.
  • edited January 2010
    EddieJ wrote: »
    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.
    We have cave!
    WWW
  • edited January 2010
    xyzzy wrote: »
    Well, I wrote my first program.. prints the numbers 1-20 on the screen.. whoopee do :smile:
    Little acorns and all that!

    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:
    ;Prints numbers 1-20 to the screen
    
    		xor a
    		ld (5C3Ch),a    ;open screen for printing
    ;
    		[COLOR="Red"][b]ld a,0          ;Redundant as A is already 0 here[/b][/COLOR]
    
    loop		inc a
    
    		ld b,0		;[COLOR="Red"][B]This *MIGHT* be redundant - see my text below[/B] [/COLOR]
    
    		ld c,a		;load bc with a
    		push af		;push a out of way for a bit
    		call 6683	;print bc
    		ld a,13		;
    		rst 10h		;print Return
    		pop af		;get back a
    		cp 20		;a-20=...
    		ret z		;exit if 20-20=0
    		jr loop		;next number!
    
    

    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! ;)
    xyzzy wrote: »
    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...
    ;   MULTICOLOUR BORDER with kludy long loop?
    
    	xor a
    	ld (5C3Ch),a
    ;	
    	call WrtMsg
    defm 16,4,17,2,22,11,7,"Hi there, partner!",0
    ;
    	ld hl,60000
    ;
    loop2	ld a,8
    ;
    loop	dec a
    	out (254),a
    
    	[B][COLOR="Red"]and a   ;Redundant as the DEC A above will set/reset the Z flag[/COLOR][/B]
    	
    	jr nz,loop
    ;
    
    [COLOR="Red"];	dec hl
    ;	ld a,h
    ;	and a		
    ;	jr nz,loop2	
    ;	ld a,l
    ;	and a
    ;	jr nz,loop2[/COLOR]
    
    [B];All of the above block (in red) can be reduced to this block:
    
            dec hl
            ld a,h
            or l
            jr nz,loop2[/B]
    
    	ret 
    ;
    ;
    ;
    WrtMsg	pop hl
    	ld a,(hl)
    	inc hl
    	push hl
    	and a
    	ret z
    	rst 10h
    	jr WrtMsg
    
    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
Sign In or Register to comment.