1

您好,我正在为 Game Boy 编写模拟器。

我正在努力使用 SUB 指令

SUB a, 0x92

给定a = 0x90

我正在做的是:

0x90 + (-0x92)

我使用 2 补码方法进行减法。

-0x92 <=>
2_complement(0x92) <=>
2_complement(10010010) <=>
01101101 + 1 <=>
01101110

所以减法等价于下面的加法:

 1001 0000 (0x90)
+0110 1110 (-0x92) 
 ---------
 1111 1110 (0xFE)

在这个过程中,没有进位,也没有半进位,所以我不设置标志。而且我认为这是一个错误,因为其他仿真器(例如BGB确实如此。请注意,结果是正确的,只有标志不正确。

所以我想真正的处理器不使用 2 补码方法,因为没有免费的方法来检索进位和半进位。

不过,我可以使用两个补码来模拟带有标志处理的 SUB 指令,还是应该依赖“经典”减法逻辑?

4

2 回答 2

2

您可以在此处找到有关如何添加/子工作和进位/溢出标志设置的答案:

我的回答:Z80 上的溢出和进位标志

我的回答是:加法器如何执行无符号整数减法?

于 2017-01-02T14:24:20.753 回答
2

真正的 CPU 在做减法时确实确实依赖于参数的反转。

首先请注意,二进制补码本身就是另一个加法(在反转所有位后加 1),因此完全这样做会很慢。

让我们看看只添加一个倒置的参数:

0x90 + (~0x92) = 0x90 + 0x6D = 0xFD 你没有进位。与正确结果相差 1。

要修复结果,您必须添加另一个,这可以通过将进位 = 1 传递给加法器来方便地完成。因此,您必须像对参数所做的那样反转传入的进位。毫不奇怪,由此产生的进位也被反转了。

示例:从 0x34 中减去 0x12:0x34 + (~0x12) + 1(反相输入进位)= 0x34 + 0xED + 1 = 0x122:无进位(取反相输出进位)和正确结果。进位为 1:0x34+0xED+0 = 0x121(无进位,结果减 1)。

但是,有些 CPU 不会反转传入和产生的进位:包括 6502(反转进位输入和输出 SBC 命令)和 32 位 ARM。他们只是颠倒了论点。

于 2017-01-03T14:32:07.287 回答