没有溢出标志的处理器如何执行带符号算术?

时间:2017-07-23 03:29:16

标签: math assembly signed integer-arithmetic 8085

我知道可以通过进位标志添加两个大于给定处理器总线大小的无符号整数。通常,对于使用溢出标志的有符号整数也是如此。但是,Intel 8085只拥有一个Sign标志,而不是一个Overflow标志,那么它如何处理有符号整数运算呢?

1 个答案:

答案 0 :(得分:7)

如您所知,溢出标志仅与有符号整数运算相关。在ALU同时具有溢出和进位标志(如x86)的处理器上,这些标志的两个都根据二进制算术运算的结果进行设置,但它直到程序员决定如何解释它们。有符号算术使用溢出标志;无符号算术使用进位标志。看错了会给你带来毫无意义的数据。

在二进制算术运算期间,有两种情况会打开溢出标志:

  1. 输入的符号位 off ,而结果的符号位 on
  2. 输入的符号位 on ,而结果的符号位 off
  3. 基本上,当结果的符号位与输入操作数的符号位不匹配时,溢出标志置位。在所有其他情况下,溢出标志被关闭。

    举几个例子:

    • 0100 + 0001 = 0101(溢出标志关闭
    • 0100 + 0100 = 1000(上的溢出标志
    • 0110 + 1001 = 1111(溢出标志关闭
    • 1000 + 1000 = 0000(溢出标志 on
    • 1000 + 0001 = 1001(溢出标志关闭
    • 1100 + 1100 = 1000(溢出标志 off

    请注意,溢出标志的状态仅取决于 三个数字的符号位;因此,您只需要查看这些位。这具有直观意义。如果你添加两个正数来得到负数,那么答案肯定是错误的,因为两个正数应该给出一个正数。相反,如果你添加两个负数并得到一个正数,那也一定是错的。添加到负数的正数永远不会溢出,因为总和位于两个输入值之间。因此,混合符号值的算法永远不会打开溢出标志。

    (显然这都假设有两个补码算法。)

    因此,即使处理器的ALU没有自动为您执行此操作,您也可以轻松计算溢出标志的状态。您需要做的就是查看三个值的符号位,特别是二进制进位到符号位的和符号位的二进制进位 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;
    }
    

    (当然,有很多不同的方法可以写这个。)

    或者,将其置于Iwillnotexist Idonotexist did in a comment:&#34;溢出可以定义为进出符号位的XOR。&#34;如果 in 中的进位不等于该特定(最左侧)位的进位 out ,则会发生溢出。

    更正式的定义是溢出标志是结果的高两位的进位的XOR。符号上,对于8位值: O = C 6 ^ C 7 ,其中 O 表示&# 34;溢出&#34; C 表示&#34;携带&#34;。这只是对我已经给出的定义的重述:如果执行不同于进位到最高位(在本例中为第7位),则会发生溢出。

    另见Ken Shirriff's article on how the overflow flag works arithmetically(这是6502的另一个流行的8位处理器)。 He also explains the implementation of the overflow flag at the silicon level in the 6502

    好的,那么进位标志是什么意思?进位标志表示无符号算术中的溢出条件。还有两种情况设置:

    1. 如果有最高有效位(符号位)的进位,则在加法期间设置进位标志。

    2. 如果有最高有效位(符号位)的借位,则在减法期间设置进位标志。

    3. 在所有其他情况下,进位标志被关闭。再一次,例子:

      • 1111 + 0001 = 0000(携带标志 on
      • 0111 + 0001 = 1000(携带标志 off
      • 0000 - 0001 = 1111(携带标志 on
      • 1000 - 0001 = 0111(携带标志 off

      为了防止它不明显,它明确指出减法与添加两个补码否定相同,因此后两个例子可以按照加法重写:

      • 0000 + 1111 = 1111(携带标志 on
      • 1000 + 1111 = 0111(携带标志 off

      ...但请注意,减法的进位是通过加法进位的反转。

      将所有这些放在一起,然后,您可以绝对地根据进位和符号标志实现溢出标志。如果您执行最高有效位(符号位),则进位标志置位。如果结果的符号位置位,则会设置符号标志,这意味着有一个进位到最高有效位。根据我们对溢出标志的定义,OF == CF ^ SF,因为溢出是符号位的进位 out 与进位进入符号位异或。如果 中的进位不等于进位输出,则会发生签名溢出。

      有趣的是,Ken Shirriff的reverse-engineering of the 8085 processor表明它实际上确实有溢出标志 - 它只是没有记录。这是8位标志状态寄存器的第1位。它被称为&#34; V&#34;并且,正如Ken explains here一样,完全按照上面讨论的方式实现,通过将进位最大有效位进行异或运算,最后进位 out 有效位 - C 6 ^ C 7 ,这些值直接来自ALU。 (他还在同一篇文章中描述了另一个未记录的标志,&#34; K&#34;标志是如何根据&#34; V&#34;标志和符号标志实现的,产生的标志是在签名比较中很有用,但有点超出了这个答案的范围。)