Game Boy Z80 CPU 有一个半进位标志,我似乎找不到太多关于何时设置/清除它的信息。
到目前为止,我所理解的是,任何 8 位加法、减法、移位或旋转操作(可能还有其他操作?)将其设置为结果的第 4 位(?),并且 DAA 指令以某种方式设置/使用它。我不确定16位指令如何影响它以及它是否受到使用某些寄存器的影响。
它是从第 3 位到第 4 位的进位,就像正常的进位标志记录从第 7 位进位一样。因此,例如要在加法中获得半进位位:
((a&0xf) + (value&0xf))&0x10
如果应该设置半进位,则给出 0x10,否则为 0。自然而然地从其他相关操作中获得一半进位 - 问题是是否有从低位到高位的进位。
从长远来看,z80 有一个 4 位 ALU,并通过执行两个 4 位操作来执行 8 位操作。因此,作为中间结果,它很自然地得到了一半的进位。
DAA 对标志感兴趣,因为如果设置了半进位,则在低半字节中添加两个加起来超过 16 的数字;这将正确地产生进位到上半字节,但会使低半字节 6 低于应有的水平,因为在应该产生进位的 10 和应该产生进位的 16 之间还有六个值。
对于 16 位操作,寄存器高字节中从位 3 到位 4 的进位设置标志。换句话说,第 11 位到第 12 位。
(请注意,上述位标记为 0-15,从最低有效到最高有效)
见这里:http ://www.z80.info/z80code.htm
16 bit arithmetic
If you want to add numbers that are more than the 0-255 that can
be stored in the A register, then the HL, IX or IY registers can
be used. Thus LD HL,1000H:LD BC,2000H:ADD HL,BC will give
A CZPSNH BC DE HL IX IY A' CZPSNH' BC' DE' HL' SP
00 000000 2000 0000 3000 0000 0000 00 000000 0000 0000 0000 0000
The flags are set as follows.
C or carry flag 1 if answer >65535 else 0
Z or zero flag not changed
P flag not changed
S or sign flag not changed
N flag 0
H or half carry flag 1 if carry from bit 11 to bit 12 else 0
由于半进位标志是 Game Boy 模拟器制造商最常见的绊脚石之一,我将冒昧地发布一个链接,指向我最近关于该主题的一个问题作为答案:
Game Boy:半进位标志和 16 位指令(尤其是操作码 0xE8)
上述线程的摘要(@gekkio 的回答):
这取决于指令,但是如果您从 8 位值的角度考虑,标志总是基于相同的位位置进行更新......无论我们谈论的是 16 位的高字节还是低字节,它都会有所不同价值。第 11 位只是高字节的第 3 位。
ADD SP, e
: H 来自第 3 位,C 来自第 7 位(来自低字节操作的标志)LD HL, SP+e
: H 来自第 3 位,C 来自第 7 位(来自低字节操作的标志)ADD HL, rr
: H 来自第 11 位,C 来自第 15 位(来自高字节操作的标志)INC rr
:无标志更新(由 16 位 inc/dec 单元执行)DEC rr
:无标志更新(由 16 位 inc/dec 单元执行)