没有溢出标志的处理器如何执行带符号的算术?
How does a processor without an overflow flag perform signed arithmetic?
我知道可以通过进位标志将两个大于给定处理器总线大小的无符号整数相加。通常,使用溢出标志的有符号整数也是如此。但是Intel 8085只有Sign标志,没有Overflow标志,那么它是如何处理有符号整数运算的呢?
如您所知,溢出标志仅与有符号整数运算相关。在 ALU 同时具有溢出和进位标志的处理器上(如 x86),both 这些标志根据二进制算术运算的结果设置,但这取决于 programmer 来决定如何解释它们。有符号算术使用溢出标志;无符号算术使用进位标志。看错了给你无意义的数据。
在二进制算术运算中有两种情况会打开溢出标志:
- 两个输入的符号位都是off,而结果的符号位是on。
- 输入的符号位都是on,而结果的符号位是off。
基本上,当结果的符号位与输入操作数的符号位不匹配时,就会设置溢出标志。在所有其他情况下,溢出标志被关闭。
举几个例子:
- 0100 + 0001 = 0101(溢出标志关闭)
- 0100 + 0100 = 1000(溢出标志开启)
- 0110 + 1001 = 1111(溢出标志关闭)
- 1000 + 1000 = 0000(溢出标志开启)
- 1000 + 0001 = 1001(溢出标志关闭)
- 1100 + 1100 = 1000(溢出标志关闭)
注意溢出标志的状态仅取决于三个数的符号位;因此,您只需查看这些位。这具有直觉意义。如果将两个正数相加得到负数,那么答案一定是错误的,因为两个正数应该得出正数。相反,如果你将两个负数相加得到一个正数,那也一定是错误的。正数与负数相加永远不会溢出,因为总和位于两个输入值之间。因此,混合符号值的算术永远不会打开溢出标志。
(显然这一切都假设了补码运算。)
因此,即使处理器的 ALU 没有自动为您计算,您也可以轻松计算溢出标志的状态。您需要做的就是查看三个值的符号位,特别是二进制进位 into 的符号位和二进制进位 out 的符号位。当一个位被进位到符号位而没有相应的进位发生时发生溢出。
这些 C 函数实现逻辑:
// For the binary (two's complement) addition of two signed integers,
// an overflow occurs if the inputs have the same sign AND ALSO the
// sign of the result is different from the signs of the inputs.
bool GetOverflowFlagForAddition(int op1, int op2, int result)
{
return (~(op1 ^ op2) & (op1 ^ result)) < 0;
}
// For the binary (two's complement) subtraction of two signed integers,
// an overflow occurs if the inputs have the same sign AND ALSO the
// sign of the result matches the signs of the inputs.
bool GetOverflowFlagForSubtraction(int op1, int op2, int result)
{
return ((op1 ^ op2) & (op1 ^ result)) < 0;
}
(当然,您可以用多种不同的方式来编写它。)
或者,换句话说:"Overflow can be defined as the XOR of the carry into and out of the sign bit."如果进位in不等于进位[=54,就会发生溢出=]out 在那个特定的(最左边的)位。
更正式的定义是,溢出标志位是结果的高两位进位异或。象征性地,对于 8 位值:O = C6 ^ C7,其中 O表示"overflow",C表示"carry"。这只是对我已经给出的定义的重述:如果进位与最高位(在本例中为位 7)的进位不同,就会发生溢出。
另见 Ken Shirriff's article on how the overflow flag works arithmetically (this is in the context of the 6502, another popular 8-bit processor). He also explains the implementation of the overflow flag at the silicon level in the 6502。
好的,进位标志是什么意思?进位标志指示 unsigned 算术中的溢出条件。再次设置了两种情况:
如果最高有效位(符号位)有进位,则在加法期间设置进位标志。
如果向最高有效位(符号位)借位,则在减法期间设置进位标志。
在所有其他情况下,进位标志被关闭。同样,示例:
- 1111 + 0001 = 0000(进位标志 on)
- 0111 + 0001 = 1000(进位标志关闭)
- 0000 - 0001 = 1111(进位标志 on)
- 1000 - 0001 = 0111(进位标志 off)
以防万一不明显,明确指出减法与补码的加法相同,所以后两个例子可以用加法重写为:
- 0000 + 1111 = 1111(进位标志 on)
- 1000 + 1111 = 0111(进位标志关闭)
...但请注意,减法的进位是加法设置的进位的倒数。
综上所述,那么,你完全可以通过进位标志和符号标志来实现溢出标志。如果您有最高有效位(符号位)的进位,则会设置进位标志。如果结果设置了符号位,则设置符号标志,这意味着最高有效位有一个进位。根据我们上面定义的溢出标志,OF == CF ^ SF,因为溢出是符号位的进位out与进位into[=异或116=] 符号位。如果进位in不等于进位out,则发生有符号溢出
不过,有趣的是,Ken Shirriff 的 reverse-engineering of the 8085 processor shows that it does, in fact, have an overflow flag—it's just undocumented. This is bit 1 of the 8-bit flag status register. It is known as "V" and, as Ken explains here 是完全按照上面讨论的方式实现的,通过将进位 异或到 最重要的位与进位 out最高位—C6^C7,这些值直接来自 ALU。 (他还在同一篇文章中描述了另一个未记录的标志,"K" 标志,是如何根据 "V" 标志和符号标志实现的,产生一个在符号比较中有用的标志,但是有点超出了这个答案的范围。)
我知道可以通过进位标志将两个大于给定处理器总线大小的无符号整数相加。通常,使用溢出标志的有符号整数也是如此。但是Intel 8085只有Sign标志,没有Overflow标志,那么它是如何处理有符号整数运算的呢?
如您所知,溢出标志仅与有符号整数运算相关。在 ALU 同时具有溢出和进位标志的处理器上(如 x86),both 这些标志根据二进制算术运算的结果设置,但这取决于 programmer 来决定如何解释它们。有符号算术使用溢出标志;无符号算术使用进位标志。看错了给你无意义的数据。
在二进制算术运算中有两种情况会打开溢出标志:
- 两个输入的符号位都是off,而结果的符号位是on。
- 输入的符号位都是on,而结果的符号位是off。
基本上,当结果的符号位与输入操作数的符号位不匹配时,就会设置溢出标志。在所有其他情况下,溢出标志被关闭。
举几个例子:
- 0100 + 0001 = 0101(溢出标志关闭)
- 0100 + 0100 = 1000(溢出标志开启)
- 0110 + 1001 = 1111(溢出标志关闭)
- 1000 + 1000 = 0000(溢出标志开启)
- 1000 + 0001 = 1001(溢出标志关闭)
- 1100 + 1100 = 1000(溢出标志关闭)
注意溢出标志的状态仅取决于三个数的符号位;因此,您只需查看这些位。这具有直觉意义。如果将两个正数相加得到负数,那么答案一定是错误的,因为两个正数应该得出正数。相反,如果你将两个负数相加得到一个正数,那也一定是错误的。正数与负数相加永远不会溢出,因为总和位于两个输入值之间。因此,混合符号值的算术永远不会打开溢出标志。
(显然这一切都假设了补码运算。)
因此,即使处理器的 ALU 没有自动为您计算,您也可以轻松计算溢出标志的状态。您需要做的就是查看三个值的符号位,特别是二进制进位 into 的符号位和二进制进位 out 的符号位。当一个位被进位到符号位而没有相应的进位发生时发生溢出。
这些 C 函数实现逻辑:
// For the binary (two's complement) addition of two signed integers,
// an overflow occurs if the inputs have the same sign AND ALSO the
// sign of the result is different from the signs of the inputs.
bool GetOverflowFlagForAddition(int op1, int op2, int result)
{
return (~(op1 ^ op2) & (op1 ^ result)) < 0;
}
// For the binary (two's complement) subtraction of two signed integers,
// an overflow occurs if the inputs have the same sign AND ALSO the
// sign of the result matches the signs of the inputs.
bool GetOverflowFlagForSubtraction(int op1, int op2, int result)
{
return ((op1 ^ op2) & (op1 ^ result)) < 0;
}
(当然,您可以用多种不同的方式来编写它。)
或者,换句话说
更正式的定义是,溢出标志位是结果的高两位进位异或。象征性地,对于 8 位值:O = C6 ^ C7,其中 O表示"overflow",C表示"carry"。这只是对我已经给出的定义的重述:如果进位与最高位(在本例中为位 7)的进位不同,就会发生溢出。
另见 Ken Shirriff's article on how the overflow flag works arithmetically (this is in the context of the 6502, another popular 8-bit processor). He also explains the implementation of the overflow flag at the silicon level in the 6502。
好的,进位标志是什么意思?进位标志指示 unsigned 算术中的溢出条件。再次设置了两种情况:
如果最高有效位(符号位)有进位,则在加法期间设置进位标志。
如果向最高有效位(符号位)借位,则在减法期间设置进位标志。
在所有其他情况下,进位标志被关闭。同样,示例:
- 1111 + 0001 = 0000(进位标志 on)
- 0111 + 0001 = 1000(进位标志关闭)
- 0000 - 0001 = 1111(进位标志 on)
- 1000 - 0001 = 0111(进位标志 off)
以防万一不明显,明确指出减法与补码的加法相同,所以后两个例子可以用加法重写为:
- 0000 + 1111 = 1111(进位标志 on)
- 1000 + 1111 = 0111(进位标志关闭)
...但请注意,减法的进位是加法设置的进位的倒数。
综上所述,那么,你完全可以通过进位标志和符号标志来实现溢出标志。如果您有最高有效位(符号位)的进位,则会设置进位标志。如果结果设置了符号位,则设置符号标志,这意味着最高有效位有一个进位。根据我们上面定义的溢出标志,OF == CF ^ SF,因为溢出是符号位的进位out与进位into[=异或116=] 符号位。如果进位in不等于进位out,则发生有符号溢出
不过,有趣的是,Ken Shirriff 的 reverse-engineering of the 8085 processor shows that it does, in fact, have an overflow flag—it's just undocumented. This is bit 1 of the 8-bit flag status register. It is known as "V" and, as Ken explains here 是完全按照上面讨论的方式实现的,通过将进位 异或到 最重要的位与进位 out最高位—C6^C7,这些值直接来自 ALU。 (他还在同一篇文章中描述了另一个未记录的标志,"K" 标志,是如何根据 "V" 标志和符号标志实现的,产生一个在符号比较中有用的标志,但是有点超出了这个答案的范围。)