【问题标题】:Can I use two complement for SUB instruction gameboy emulation?我可以在 SUB 指令 gameboy 仿真中使用两个补码吗?
【发布时间】:2017-01-02 13:26:17
【问题描述】:

您好,我正在为 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 确实如此。 注意结果是正确的,只有flags不正确。

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

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

【问题讨论】:

    标签: emulation z80 gameboy


    【解决方案1】:

    真正的 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。他们只是颠倒了论点。

    【讨论】:

    • 我认为这个答案的关键部分可能是:结果进位也是倒置的。所以原作者说的对,加法形式既不产生进位也不产生半进位。但他应该反转该结果并设置进位和半进位标志。这样说公平吗?
    【解决方案2】:

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

    My answer to: Overflow and Carry flags on Z80

    My answer to: How does an adder perform unsigned integer subtraction?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-10-24
      • 2014-03-27
      • 2013-06-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多