您好我正在为Game Boy编写模拟器。
我正在与SUB intruction挣扎
print calendar.get_properties([dav.DisplayName()])
给出SUB a, 0x92
。
我在做的是:
a = 0x90
我使用2补充方法进行减法。
0x90 + (-0x92)
因此,减法等同于以下添加:
-0x92 <=>
2_complement(0x92) <=>
2_complement(10010010) <=>
01101101 + 1 <=>
01101110
在此过程中,没有进位,没有半进位,所以我没有设置标志。而且我认为这是一个错误,因为其他仿真器(如BGB)也是如此。 请注意,结果是正确的,只有标志不正确。
所以我认为真正的处理器不使用2补码方法,因为没有自由的方法来检索进位和半进位。
但是,我可以使用两个补码来模拟带有标志处理的SUB指令,还是应该依赖“经典”减法逻辑?
答案 0 :(得分:1)
你可以在这里找到如何设置add / sub work和carry / overflow标志的答案:
答案 1 :(得分:1)
真正的CPU在进行减法时确实依赖于参数的反转。
首先请注意,两个补码本身是另一个加法(在反转所有位后加1),所以完全相同的做法会很慢。
让我们看看只添加一个倒置的参数:
0x90 +(~0x92)= 0x90 + 0x6D = 0xFD,你没有进位。从正确的结果中减去1。
要修复结果,必须添加另一个,这可以通过将carry in = 1传递给加法器来方便地完成。因此,您必须像对待参数一样完成转换进位。 毫不奇怪,结果携带也是倒置的。
示例:从0x34减去0x12: 0x34 +(~0x12)+ 1(反向输入进位)= 0x34 + 0xED + 1 = 0x122:无执行(取反输出进位)并校正结果。 传入进位为1:0x34 + 0xED + 0 = 0x121(无执行,结果减1)。
然而,有些CPU不会反转输入和结果进位:包括6502(反向进位输入和输出SBC命令)和32位ARM。他们只是颠倒了论点。