0

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.

Sep Roland
  • 33,889
  • 7
  • 43
  • 76
Stevo
  • 1,424
  • 11
  • 20
  • 2
    There is other register pair.. HL... It works in the same manner... Guess what H and L stands for... – Selvin Feb 04 '23 at 15:11
  • 1
    You wrote the instruction the way a disassembler displays it or you write it in assembly. It uses the "natural" order, humans like their most significant byte on the left and the least significant on the right. Same story for register pairs, BC has the most significant register on the left. Your emulator however sees 0x01 0x34 0x12. Little-endian, 0x34 is first. Only the memory bus interface has the endian detail. – Hans Passant Feb 04 '23 at 15:55
  • 2
    Values in asm source are *values*, not encodings; they use normal most-significant-digit first order. – Peter Cordes Feb 04 '23 at 16:44

2 Answers2

3

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:

  • With the encoding of immediates in instructions, such as ld bc, 0x1234: looking at the individual bytes of the machine code for this instruction, we will see 0x01 0x34 0x12, storing the 0x1234 in little endian byte order.

  • With a 16-bit value as data in memory, and looking at the individual bytes in memory, needs an endian-ness, so use little endian.

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.

Erik Eidt
  • 23,049
  • 2
  • 29
  • 53
  • That seems to make sense, thank you for providing a clear explanation. – Stevo Feb 04 '23 at 17:50
  • If you're ever in doubt, sometimes the easiest way is to test it yourself. Now, emulators are not always accurate, but if you don't have the real hardware, they're your best option. For something like this you can trust nearly all emulators to get it right – puppydrum64 Feb 09 '23 at 16:41
  • @puppydrum64, this is a good comment, but more appropriate to direct to the OP rather than me. – Erik Eidt Feb 09 '23 at 16:42
  • Whoops, I commented on the wrong post! – puppydrum64 Feb 09 '23 at 16:43
0

Is a manufacturer datasheet reliable source? Z80 user manual And of course in memory after opcode is firstly 0x34 then 0x12

Peter Plesník
  • 524
  • 1
  • 2
  • 7
  • I have that manual... it just says "Upon the execution of an LD HL, 5000h instruction, the HL register pair contains 5000h". Not terribly clear. – Stevo Feb 04 '23 at 15:27
  • The question could have been answered by page 46 / 47 of the user manual which describes how ``ld de,0659h`` is encoded, unfortunately figure 37 was botched and shows ``and 7`` instead :-) – Stefan Drissen Feb 05 '23 at 21:30