Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Z80 Register Endianness

Considering this sample code:

ZilogZ80A cpu = new ZilogZ80A();
cpu.GeneralRegisters.H.FromUInt(229);
cpu.GeneralRegisters.L.FromUInt(90);
Console.WriteLine("H : " + cpu.GeneralRegisters.H.ToString());
Console.WriteLine("L : " + cpu.GeneralRegisters.L.ToString());
Console.WriteLine("HL: " + cpu.GeneralRegisters.HL.ToString());

Console.WriteLine("Load 23268 (0x5AE4) into register HL...");
cpu.GeneralRegisters.HL.FromUInt(23268);

Console.WriteLine("H : " + cpu.GeneralRegisters.H.ToString());
Console.WriteLine("L : " + cpu.GeneralRegisters.L.ToString());
Console.WriteLine("HL: " + cpu.GeneralRegisters.HL.ToString());

Which is doing the following:

  • Load 229 (decimal) into register H
  • Load 90 (decimal) into register L
  • Print out the values (hex, binary MSB, decimal) of the H, L and HL registers
  • Load 23268 (decimal) into register HL
  • Print out the values of the H, L and HL registers again.

Sample output:

H : 08-bit length register (@45653674): 0x00E5 | MSB 0b11100101 | 229
L : 08-bit length register (@41149443): 0x005A | MSB 0b01011010 | 90
HL: 16-bit length register (@39785641): 0x5AE5 | MSB 0b01011010 11100101 | 23269
Load 23268 (0x5AE4 into register HL...
H : 08-bit length register (@45653674): 0x00E4 | MSB 0b11100100 | 228
L : 08-bit length register (@41149443): 0x005A | MSB 0b01011010 | 90
HL: 16-bit length register (@39785641): 0x5AE4 | MSB 0b01011010 11100100 | 23268

Now for the questions:

  1. Are the above assumptions (and sample output) on how the registers function correct?
  2. Do the other register pairs (AF, BC, DE) function the exact same way?
  3. If the answer to 1. and 2. is yes, why is the Z80 then considered little endian? When the HL register contents gets written to memory the L byte goes first, but (when reading them sequentially afterwards the bytes surely are in big endian order)?
like image 326
ChristopheD Avatar asked Feb 07 '14 23:02

ChristopheD


People also ask

Do registers have endianness?

The register is neither big-endian nor little-endian; it's just a register holding a 32-bit value. The rightmost bit is the least significant bit, and the leftmost bit is the most significant bit. Some people classify a register as a big-endian, because it stores its most significant byte at the lowest memory address.

What determines endianness?

Broadly speaking, the endianness in use is determined by the CPU. Because there are a number of options, it is unsurprising that different semiconductor vendors have chosen different endianness for their CPUs.

Is Game Boy Little Endian?

In the case of the Game Boy the order is 0xFF16 - in other words the least significant byte is first in memory. This scheme is known as little-endian and its opposite is known as big-endian.

Does endianness affect bit order?

Bit order usually follows the same endianness as the byte order for a given computer system. That is, in a big endian system the most significant bit is stored at the lowest bit address; in a little endian system, the least significant bit is stored at the lowest bit address.


2 Answers

Yes — HL is composed of H as the most significant byte, L as the least. If you perform a 16-bit operation like ADD HL,BC then carry from the top bit of L+C will flow into the computation of H+B. All the register pairs are alike in this regard.

That's because the logical order things are written in isn't related to endianess. E.g. in C you don't have to write 0x0001 on some platforms to equal 0x0100 on others. When writing, you write the most significant first.

The z80 is little endian because if you were to store HL to memory, L would be written a byte before H. If you were to read, L would be read from the address before H.

like image 147
Tommy Avatar answered Oct 07 '22 05:10

Tommy


ld hl, $1234
ld ($fc00), hl

At this point, H = $12, L = $34, as your code suggests. The byte at $fc00 = $34, and the byte at $fc01 = $12. So if you subsequently do:

ld hl, $5678
ld ($fc02), hl

($fc00) = $34, ($fc01) = $12, ($fc02) = $78, and ($fc03) = $56. So reading byte by byte from $fc00, memory would be $34127856, instead of $12345678, because Z80 is little endian.

like image 2
James Avatar answered Oct 07 '22 04:10

James