z88dk / z88dk

The development kit for over a hundred z80 family machines - c compiler, assembler, linker, libraries.
https://www.z88dk.org
Other
871 stars 168 forks source link

How is ADD DE, buffer assembled? #2580

Closed Candid-Moe closed 1 week ago

Candid-Moe commented 1 week ago

I'm learning Z80 and made this program to test how to code and access parts of a struct via a pointer.

defvars 0 {
    size     ds.b   32
    name     ds.w   0x1234
    status   ds.b  15
    }

org 0x4000

    LD DE, buffer
    ADD DE, name
    LD A, (DE)

buffer:
    db 4
    dw 0x5051
    db 3

When I look at the generated code, I found that ADD DE, name was compiled to this

0003 e521200019545de1 ADD DE, name

or image

which make sense: ADD DE, nn is not a Z80 code and Z80asm translate it into several machine ops.

How does it works? What other "instructions" is Z80asm able to convert to machine codes? Where I can read more about this?

dbolli commented 1 week ago

I think you want

defvars 0 {
    size     ds.b   1
    name     ds.w   1
    status   ds.b  1
    }

Then you could do

    LD DE,(buffer+name) ; DE = word at address buffer + 1
    LD A,(DE)   ; A = contents of address $5051

See Tool---z80asm---directives wiki entry for more info.

Also please see Z80 Assembly Language Programming by Lance A. Leventhal if you haven't already downloaded a copy.

Regards, Derek.

feilipu commented 1 week ago

Which make sense: ADD DE, nn is not a Z80 code and Z80asm translate it into several machine ops. How does it works?

The z88dk-z80asm assembler is both a "synthetic" assembler and a "MACRO" assembler. By that I mean it is able to synthesise a variety of different opcodes into equivalent binary assembly, as well as to translate MACROs into opcodes, which also may or may not be synthetic on specific machines.

Usually synthetic opcodes are only created where there are no side effects generated from the code swap, such as setting flags or trashing other registers, but that is not always the case.

This z88dk-z80asm capability is quite uncommon and I don't know of another Z80 assembler with similar capabilities. Although TASM can be augmented by the user to emulate this feature by adding appropriate translation.

z88dk-z80asm does this synthetic assembly for several reasons.

  1. There are multiple machine variants supported and often makes it easier to write assembly for these different variants without conditional assembly, if for example opcodes supported on the Z80 are synthesised for the GBZ80, or vice versa.

  2. Avoiding stupid typos. It easy to write something like ld h,b ld l,e and have that do entirely the wrong thing, when you really meant to do ld hl,bc (or ld hl,de). By having these as synthetic 16 bit instructions it avoids these silly mistakes.

  3. Makes code generally easier to read, particularly where int (16 bit) values are being handled. Having synthetic instructions for 16 bit data types doesn't make things faster or smaller, but it does make the code cleaner and arguably easier to read.

What other "instructions" is Z80asm able to convert to machine codes? Where I can read more about this?

The complete list of synthetic operations is contained within the full list of opcodes supported across all variants. The list is here (check about halfway through to see the equivalence for opcode, machine variant and binary), and it is found within the z88dk-z80asm wiki page.

feilipu commented 1 week ago

Please reopen if you've follow on questions.