Game Boy:什么是“半进位”?

发布于 2024-12-27 08:01:52 字数 178 浏览 2 评论 0原文

Game Boy Z80 CPU 有一个半进位标志,我似乎找不到太多关于何时设置/清除它的信息。

到目前为止我所理解的是,任何 8 位加法、减法、移位或旋转操作(也许还有其他操作?)将其设置为结果的第 4 位(?),并且 DAA 指令以某种方式设置/使用它。我不确定 16 位指令如何影响它以及它是否受到使用某些寄存器的影响。

The Game Boy Z80 CPU has a half-carry flag, and I can't seem to find much information about when to set/clear it.

What I understand so far is that any 8-bit add, subtract, shift, or rotate operation (and maybe others?) set it to bit 4 of the result(?), and the DAA instruction sets/uses this somehow. What I'm not sure is how 16-bit instructions affect it and whether it's affected or not by the use of certain registers.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

浅忆 2025-01-03 08:01:52

它是从位 3 到位 4 的进位,就像正常进位标志记录从位 7 进位一样。因此,例如要在加法中获取半进位位:

((a&0xf) + (value&0xf))&0x10

如果应设置半进位,则给出 0x10,否则为 0。从其他相关操作中获得半进位是很自然的事情 - 问题是是否存在从低半字节到高半字节的进位。

从长远来看,z80 有一个 4 位 ALU,通过执行两个 4 位运算来执行 8 位运算。所以它很自然地得到半进位,作为中间结果。

DAA 对标志感兴趣,因为如果设置了半进位,则在低半字节中添加了加起来超过 16 的两个数字;这将正确地在高半字节中产生进位,但会使低半字节 6 低于应有的值,因为在应该生成进位的 10 和它生成进位的 16 之间还有 6 个值。

It's the carry from bit 3 to bit 4, just like the normal carry flag records carry from bit 7. So, e.g. to get the half carry bit in an add:

((a&0xf) + (value&0xf))&0x10

Which gives 0x10 if half carry should be set, 0 otherwise. Getting half carry from the other relevant ops follows naturally - the questions is whether there was carry from the low nibble to the high.

To put things in perspective, the z80 has a 4bit ALU and performs 8bit ops by doing two 4bit ops. So it gets half carry very naturally, as an intermediate result.

DAA is interested in the flag because if half carry is set then two digits that add up to more than 16 were added in the low nibble; that will have correctly produced carry into the upper nibble but will have left the low nibble 6 lower than it should be, since there were six more values between 10, when it should have generated carry, and 16, when it did.

灼痛 2025-01-03 08:01:52

对于 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

For 16-bit operations, the carry from bit 3 to bit 4 in the register's high byte sets the flag. In other words, bit 11 to bit 12.

(Note the above bits are labeled 0-15, from least to most significant)

See here: 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
再见回来 2025-01-03 08:01:52

由于半进位标志是 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 单元执行)

Since the half-carry flag is one of the most common stumbling blocks for Game Boy emulator makers, I'll take the liberty to post a link to a recent question of mine regarding the subject as an answer:

Game Boy: Half-carry flag and 16-bit instructions (especially opcode 0xE8)


A summary of the above thread (answer by @gekkio):

It depends on the instruction, but the flags are always updated based on the same bit positions if you think in terms of 8-bit values...it just varies whether we're talking about the high or low byte of the 16-bit value. Bit 11 is just bit 3 of the high byte.

  • ADD SP, e: H from bit 3, C from bit 7 (flags from low byte op)
  • LD HL, SP+e: H from bit 3, C from bit 7 (flags from low byte op)
  • ADD HL, rr: H from bit 11, C from bit 15 (flags from high byte op)
  • INC rr: no flag updates (executed by the 16-bit inc/dec unit)
  • DEC rr: no flag updates (executed by the 16-bit inc/dec unit)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文