• Please review our updated Terms and Rules here

Z80 assembly inconsistency

alank2

Veteran Member
Joined
Aug 3, 2016
Messages
2,255
Location
USA
Why sometimes have "a," and sometimes not? Even in similar commands SUB s vs SBC A,s. Any reason for this? Would assemblers accept getting it wrong "ADD B" or "SUB A,B"?

1654825614687.png
 
I think that it's because there are 16-bit versions of those instructions (that use HL).
The instructions that are 8-bit only assume A.
 
And the official set of Z80 assembly opcodes is very incomplete. For example you can divide the IX and IY pairs into 2 8-bit registers, like HL, DE and BC.
So it's possible to have ADD A,IXL in theory. In fact, you'd prefix an ADD A,L with the DD (hex) prefix. There are a lot more Z80 instructions than the manual would indicate.
 
Why didn't they just put the "A," on the sub instructions for consistency? In other words why have to remember which referenced the accumulator and which didn't. Just always show both operands. Wouldn't it be a total pain to try to remember which has he "A," and which doesn't? Or did assemblers handle it just fine if one used SUB A,B?

1654831014550.png
1654831029418.png
 
Like I said, if there's a 16-bit version then you have to specify; if there isn't; you don't. In my 40+ years of programming Z80 assembly I don't think I've ever had to think about it.
 
Can't explain the inconsistency, the MicroSoft's M80 from 1981 certainly shows it:
Code:
        MACRO-80 3.44   09-Dec-81       PAGE    1


                                        .z80
                                        org     0
Q 0000'   97                            sub     a,b
  0001'   90                            sub     b
  0002'   80                            add     a,b
O 0003'   C6 00                         add     b
  0005'   88                            adc     a,b
O 0006'   CE 00                         adc     b
  0008'   98                            sbc     a,b
O 0009'   DE 00                         sbc     b
                                        end

Haven't spent any time thinking about it, but perhaps it was one of those "bug-for-bug compatibility" things. Note, in none of these examples I tried did both syntax work.
 
I see the original Zilog Z80 CPU documentation shows the same inconsistency, so it probably did not originate with MicroSoft. Perhaps Zilog engineers (mistakenly) thought such a thing was necessary/helpful for parsing - which contradicts the overly-complex parsing required for the "kitchen sink" mnemonic "LD". Probably one of those things we'll never know. Note, "zmac" (which is not necessarily a gold-standard of modern assemblers) handles both styles of operands, correctly:

Code:
                        .z80
0000                    org     0
0000  80                add     a,b
0001  80                add     b
0002  88                adc     a,b
0003  88                adc     b
0004  90                sub     a,b
0005  90                sub     b
0006  98                sbc     a,b
0007  98                sbc     b
0008  A0                and     a,b
0009  A0                and     b
000A  A8                xor     a,b
000B  A8                xor     b
000C  B0                or      a,b
000D  B0                or      b
000E  B8                cp      a,b
000F  B8                cp      b
0010                    end
 
geowar1 has already given you the answer...

If there are both 8 and 16 bit instructions using the same mnemonic (e.g. ADD, ADC, SBC) the 'A' operand should be present.

If there is only an 8 bit instruction (e.g. SUB) the 'A' operand should not be present.

Therefore, ADD, ADC and SBC should have the 'A' for the 8-bit incarnation of the instruction.

The SUB doesn't require the 'A', because there is no 16-bit SUB instruction (only a SBC - which does require the 'A').

This doesn't mean that Microsoft and Digital Research (and others) coded their assembler products correctly of course.

Dave
 
Can't explain the inconsistency, the MicroSoft's M80 from 1981 certainly shows it:
Code:
        MACRO-80 3.44   09-Dec-81       PAGE    1


                                        .z80
                                        org     0
Q 0000'   97                            sub     a,b
  0001'   90                            sub     b
  0002'   80                            add     a,b
O 0003'   C6 00                         add     b
  0005'   88                            adc     a,b
O 0006'   CE 00                         adc     b
  0008'   98                            sbc     a,b
O 0009'   DE 00                         sbc     b
                                        end

Haven't spent any time thinking about it, but perhaps it was one of those "bug-for-bug compatibility" things. Note, in none of these examples I tried did both syntax work.

Well, this is more an issue with m80 that with Zilog, I think. m80 is trying its best to understand... looking at the code generated, I created a short file and then used zsid to disassemble it. You can see that m80 tried to interpret some things as immediate, instead of a register.

0100 SUB A 0101 SUB B 0102 ADD A,B 0103 ADD A,00 0105 ADC A,B 0106 ADC A,00 0108 SBC A,B 0109 SBC A,00

So the sub a,b turned into a great way to zero A :)
 
Going back to the original Intel and DRI assemblers, registers were equated constants. Thus, one can write the following and it means the same thing in DRI ASM:
Code:
 0100                   org     100H

                Entry:
 0100 80                add     b
 0101 80                add     0
 
geowar1 has already given you the answer...

If there are both 8 and 16 bit instructions using the same mnemonic (e.g. ADD, ADC, SBC) the 'A' operand should be present.

If there is only an 8 bit instruction (e.g. SUB) the 'A' operand should not be present.

Therefore, ADD, ADC and SBC should have the 'A' for the 8-bit incarnation of the instruction.

The SUB doesn't require the 'A', because there is no 16-bit SUB instruction (only a SBC - which does require the 'A').

This doesn't mean that Microsoft and Digital Research (and others) coded their assembler products correctly of course.

Dave
That describes the pattern, but does not explain the logic/rationale. Parsers are perfectly capable of understanding the difference between 16-bit and 8-bit operands, so I don't really see why it had to be that way. It appears that Zilog started it all, at least their CPU documentation shows the anomaly. Unless Microsoft was contracted by Zilog to produce the first Z80 assembler and just did it that way for other reasons, so Zilog documentation followed that lead.
 
>>> That describes the pattern, but does not explain the logic/rationale. Parsers are perfectly capable of understanding the difference between 16-bit and 8-bit operands, so I don't really see why it had to be that way.

The fact that there is a pattern implies (to me at least) that this was an internal design decision rather than a random 'throw of the dice'. We may never know (of course) whether this is true or not though...

The syntax may have originated internally to ensure a source code upgrade path with future Zilog processors.

Dave
 
>>> That describes the pattern, but does not explain the logic/rationale. Parsers are perfectly capable of understanding the difference between 16-bit and 8-bit operands, so I don't really see why it had to be that way.

The fact that there is a pattern implies (to me at least) that this was an internal design decision rather than a random 'throw of the dice'. We may never know (of course) whether this is true or not though...

The syntax may have originated internally to ensure a source code upgrade path with future Zilog processors.

Dave
Right, there may have been some logic to it, but I just don't see it, yet. To me, the inconsistency was not necessary. Either "sub a,b" (etc) could have been chosen or else "sbc b" and "sbc bc" could have been chosen. Things like this just reinforce my personal dislike of Zilog mnemonics.
 
Yeah, same here… it's the 8080 mnemonics that seem absurd to me.
BTW: ZASM4 handles both syntaxes. (<https://github.com/hperaza/ZSM4>)
The Intel mnemonics actually follow the machine language architecture, so they always make more sense to me. I started out on 8080, and always used the DRI tools. So, when Z80 came along, used Z80.LIB to get Z80 instructions. Zilog mnemonics "hide" the underlying asymmetry of the machine language architecture, so did not make sense to me.
 
On the other hand, 8080 mnemonic syntax are very straightforward, with none of the strange end-cases noted in the Z80 convention. Just remember that "M" stands for memory (HL) and that HL is the 16 bit accumulator. And parentheses mean nothing, except in constant expressions.

I can code in either 8080 or Z80, BTW. Comes from having to do so much of both back in the day. Same for octal vs. hexadecimal.
 
To be honest, I really like the simplicity of ld x,y and I've always thought I'd be more comfortable with z80 assembly. Not that I'm very good at either 8080/z80. I guess I was hoping for the simplicity of consistency here and I don't see why they wouldn't have just made them all consistently the same. If they are operating on a, why not have it say "xor a,b" as that makes more sense.
 
To be honest, I really like the simplicity of ld x,y and I've always thought I'd be more comfortable with z80 assembly. Not that I'm very good at either 8080/z80. I guess I was hoping for the simplicity of consistency here and I don't see why they wouldn't have just made them all consistently the same. If they are operating on a, why not have it say "xor a,b" as that makes more sense.
At the risk of reopening the whole "Intel vs Zilog mnemonics" war, I'll just say that when I first saw Zilogs mnemonics I thought "cool". But then I saw things like that "ld" was a crude catch-all for all move, load, and store operations. Plus, the mnemonics imply a symmetry that does not exist (you can do "sbc a,b" but not "sbc h,b", etc ad nausium). You basically still need to know the underlying machine language in order to program effectively, so I just chose to stick with Intel mnemonics where that architecture was obvious.
 
Back
Top