Z80寄存器字节序

5

考虑以下示例代码:

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());

以下是要执行的操作:

  • 将229(十进制)加载到H寄存器中
  • 将90(十进制)加载到L寄存器中
  • 打印出H、L和HL寄存器的值(十六进制、二进制MSB、十进制)
  • 将23268(十进制)加载到HL寄存器中
  • 再次打印出H、L和HL寄存器的值。

示例输出:

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

现在来看一下问题:

  1. 上述假设(和样本输出)关于寄存器的功能是否正确?
  2. 其他寄存器对(AF,BC,DE)是否完全相同?
  3. 如果问题1和2的答案是肯定的,为什么Z80被认为是小端?当HL寄存器内容写入内存时,L字节先行,但是(后续按顺序读取时字节肯定是大端序)?

3
字节序(Endianess)适用于内存中的排列顺序,但不适用于加载立即值到寄存器。如果你要将 0x5AE5 写入内存,则字节序决定它是以 5AE5 还是 E55A 的形式存储进去。 - Marc B
2个回答

8
是的 - HL由最高有效字节H和最低有效字节L组成。如果您执行像ADD HL,BC这样的16位操作,则来自L + C的最高位进位将流入H + B的计算中。在这方面,所有寄存器对都是相同的。
这是因为逻辑顺序与字节序无关。例如,在C中,您不必在某些平台上写入0x0001以使其等于其他平台上的0x0100。在编写时,您首先编写最重要的内容。
z80是小端的,因为如果您要将HL存储到内存中,则会先写入L一个字节再写入H。如果要读取,则会从地址之前读取L,然后才会读取H

谢谢!但让我感到困惑的是,如果您首先将L(5A)写入内存(例如,内存位置1000),然后再将H(E5)写入内存(位置1001),当按顺序读取时它们仍然以“相同”的方式排列(5AE5)。或者上面的示例输出有什么问题吗? - ChristopheD
2
我不完全理解这个问题,但是:如果你将HL写入内存,那么Z80会先写L,然后是H。如果模拟器将HL放在屏幕上供人类使用,它会打印H然后是L,因为它知道你正在输出一个16位的数量,而这就是它们的书写方式。相反,如果你将5AE5存储到内存中,然后输出内存给人看,它会逐字节打印,因为这就是内存的书写方式。如果你从该地址读取HL,它将先读取L,然后是H,得到的16位值为E55A - Tommy

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

根据您的代码指示,此时H = $12,L = $34。$fc00处的字节为$34,$fc01处的字节为$12。所以如果您随后执行以下操作:

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

($fc00) = $34,($fc01) = $12,($fc02) = $78,和 ($fc03) = $56。所以从$fc00逐字节读取内存,内存将会是$34127856,而不是$12345678,因为Z80采用小端序。


这很令人困惑。难道不应该是$56781234吗?我认为小端序并不会到半字节级别。 - S.S. Anne
是的,因为每个单词都是两个字节。 - S.S. Anne
1
每个十六进制数字是一个字节?不,那被称为半字节。一个字节是2个十六进制数字/半字节。 - nonchip

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接