assemblyemulationendiannessinstruction-setz80

Z80 16-Bit Load Instruction and Endianness


I'm writing a ZX Spectrum emulator in C# "for fun" (I think I regret starting already).

I know the Z80 is little endian, so in RAM the low-order byte is stored first.

What I can't seem to find a definitive answer to, is how it behaves with a 16-bit LD instruction.

For example:

LD BC, 0x1234

After this, does B contain 0x12 and C contain 0x34 or vice-versa?

So, after the above, if I execute:

LD A, 0x56
LD (BC), A

Will memory 0x1234 or 0x3412 contain 0x56?

It would be nice if someone could provide a link to a reliable source.


Solution

  • Endian-ness only comes into play when we break a 16-bit value into two 8-bit pieces, and there is a choice of approaches, which happens when such a 16-bit value is stored in memory so, for example:

    However, if the BC register pair is loaded with a value 0x1234, then that's the memory address that indirect use of BC will work with.  There's no issue of endian-ness with this, since we're not looking at the individual bytes in this scenario.

    Now, if you want to know how the BC register composes from B and C then we have to know which is the high order and which is the low order.

    From the manual:

    PUSH BC is PUSH B then C

    So, that means that the stack memory will have the value from C then the value from B at the address +1 higher than where C was stored.  Since 16-bit data in memory is stored using little endian byte order, we can conclude that C is the low order and B is the high order of the BC 16-bit register pair.

    Thus, BC is B * 256 + C.  Let's note though, that this is simply by definition, but doesn't really go to endian-ness — since there's no "addressing" of the individual bytes, there's also no other ordering as there is with memory (due to memory's having of both addresses and values).

    However, the choice of which is high and which is low doesn't change that together they hold the value 0x1234, as per our examples.