在做位运算实现函数功能的相关题目时,我遇到了一个很重要的问题,两个有符号整数做加/减法时,用来判断是否溢出的OF位该如何判断?

最后整理出3个方法,整理并分享出来,希望对您有帮助。

1.根据计算机组成原理课上学习的知识

OF = Cn ⊕ Cn-1

注意这里的Cn和Cn-1并不是指x+y或x-y结果补码的最高有效位的左边的进位以及最高有效位的数值,而是指x+y或x-y结果补码的最高有效位以及次高有效位的进位情况,若有进位,该值为1,否则为0。
下面以8位机器数(首位为符号位)为例简单说明

    1 0 0 0 0 0 0 1
 +  1 0 0 0 0 0 0 0
 --------------------
  1 0 0 0 0 0 0 0 1

两数相加的补码运算如上,[x]补 + [y]补 = [x + y]补
在结果中,最高有效位进行的运算是1 + 1有进位,因此Cn = 1;次高有效位进行的运算是0 + 0没有进位,因此Cn-1 = 0。
1 ⊕ 0 = 1,即OF = 1,发生溢出。

OF = A7 ⊕ B7 ⊕ C7 ⊕ C8

以8位数运算举例:
8位二进制数A:A7 A6 A5 A4 A3 A2 A1 A0
8位二进制数B:B7 B6 B5 B4 B3 B2 B1 B0
A +/- B 的结果9位二进制数C:
C8 C7 C6 C5 C4 C3 C2 C1 C0
OF = A7 ⊕ B7 ⊕ C7 ⊕ C8
这里的C8就是CF位(carry)。
方法2参考来源:CPU是如何检测溢出的

3.先思考一下问题的本质——什么时候发生溢出?
在两个加数(因为做减法也是通过补码加法实现的)的符号位相同且与和的符号位不同的情况下才会发生溢出。说明两个正数相加得出负数,或者两个负数相加得出正数,这显然是不正确的。因此只要

看 加数1,加数2,和 3个数的符号位即可。
1 1 0 或者 0 0 1发生溢出,OF = 1。

(可以看到上面举的例子就是1 1 0的情况)

在你遇到这样的一个例子127 - (-128)可能会产生怀疑

    0 1 1 1 1 1 1 1
 +  1 0 0 0 0 0 0 0
 --------------------
    1 1 1 1 1 1 1 1

在这个例子中根据上面的方法算出OF = 0,可是明明结果是一个很大的正数,超过了8位带符号机器数所能表示的范围,结果却是-1。
其实并不是算OF的方法错了,做加法运算的这个步骤的确没有溢出。而是在第二个加数为了求其补码时,需要各位取反之后,末位加1,在求补码的时候取负运算发生了溢出。

总结

计算OF的方法的本质就是
最高位运算的进位 ⊕ 次高位运算的进位
由此延申出几种判断方法。
个人认为方法3最容易判断,首推方法3。不过要特别注意第二个数是最小负数的情况。并且在位运算实现函数功能时方法3也是最容易实现的,因为方法1、2需要知道最高有效位的进位,需要知道前一位是否有进位,用前一位的进位,本位加数1的符号位,本位加数2的符号位相加是否与和的当前符号位相等判断最高有效位是否进位,这个很难处理。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐