5

我正在制作一个 6502 仿真器,但一开始我就被卡住了(或者我认为我至少是卡住了)(实现 ADC 操作)。问题是我必须确定是否有进位或溢出。问题是,在我的实现中,我无法真正掌握它们之间的区别。我知道进位是在操作后存在第 9 位时,并且我知道当结果大于 255 时会发生溢出。这不是确定进位和溢出标志是一回事吗?

if(result > 255) { 
    carry = 1;
    overflow = 1;
} else { 
    carry = 0; 
    overflow = 0;
}

这不正确吗?如果不是,什么是正确的,为什么?

4

1 回答 1

14

溢出标志指示数字的符号何时不正确地更改。因此,如果将两个正数相加并得到否定结果,则会出现溢出。如果将两个负数相加并得到正结果,也会出现溢出。

添加两个不同的符号时不会溢出,因为范围不允许。最小的正数加上最大的负数是 0 + (-128),这很合适——0 加上任何适合 8 位的东西显然都适合 8 位。最小的负数加上最大的正数是-1 + 127 = 126。适合。

(编辑:即使有进位,0 + -128 + 1 = -127,适合,-1 + 127 + 1 = 127,适合)

因此,如果两个具有相同符号的输入产生具有不同符号的结果,则会设置溢出。否则就很清楚了。

您可以将其表示为对符号位的简单按位运算。假设你有 a + b = c。

a ^ b

如果符号不同,符号位将有一个 1。你想知道相反的情况。所以:

~(a ^ b)

如果符号相同,则在符号位中给出 1. 这是测试的第一部分。假设 a 和 b 具有相同的符号,您可以针对其中任何一个测试 c。这次你确实想测试差异,所以这只是:

a ^ c

您需要在测试的两个部分中设置测试位,因此您可以将它们与二进制和(留下大量括号以链接到口头推理):

(~(a ^ b))&(a ^ c)

你只需要符号位,所以屏蔽掉它:

(~(a ^ b))&(a ^ c)&0x80

这将评估0x00是否应该清除溢出标志以及0x80是否应该设置它。因此,只需将其转移到位。

(除此之外:虽然在 6502 上很多指令设置了标志并且只有一个暴露了状态寄存器,所以仿真器经常以任何方便的形式单独保存标志并根据需要组合状态寄存器,在这种情况下你不会打扰移位和组合,您只需存储该结果)

于 2013-05-31T15:52:32.693 回答