相关阅读数字IC基础https://blog.csdn.net/weixin_45791458/category_12365795.html?spm1001.2014.3001.5482https://blog.csdn.net/weixin_45791458/category_12365795.html?spm1001.2014.3001.5482首先说明本篇文章并不涉及补码运算正确性的证明仅是对补码运算在有符号数和无符号数中运行进行讨论。补码运算最大的作用在于消除计算机内部的减法器所以实际上一个计算机中只有加法器而并不存在减法器所有的减法操作有符号数减法、无符号数减法都是使用加法器完成的。下面是补码运算的公式其中x和y可以理解为一般意义上的十进制数比如x为2y为-1则按照补码运算公式得到的是1的补码x为1y为-5则按照补码运算公式得到的是-4的补码。注意这里得到十进制数的补码需要先将其转换为二进制原码然后再转换为二进制补码。其中需要注意的是两个补码相加必须保证这两个补码有相同的位数当其中两个补码位数不同时需要将位宽短的那个补码符号拓展至位宽长的那个补码才能相加。具体操作如下当十进制数-1的4位二进制补码1111想和十进制数2的8位二进制补码00000010相加时必须先将1111符号拓展至11111111才能与00000010相加得到结果00000001即十进制数1的8位二进制补码。两个二进制补码相加后的位宽不变例如两个8位二进制补码相加结果仍然为8位二进制补码这就导致了当两个正数或两个负数相加时可能产生溢出通俗理解就是结果不能再用8位二进制补码表示了即需要用9位二进制补码表示。比如对于4位二进制补码可以表示的十进制数范围是-8到7此时当两个十进制数4的4位二进制补码的相加时结果本应该为十进制数8的4位二进制补码但很遗憾4位二进制补码最高只能表示7并不能表示8。溢出很好发现当两个正数二进制补码符号位为0相加得到了负数二进制补码符号位为1或两个负数相加得到了正数则可认为产生了溢出。使用上面的44的例子说明4的4位二进制数补码为010001000100得到1000即-8的二进制补码两个正数相加得到了负数这是不可能的这就是溢出。如何解决这个问题呢如果使用4的5位二进制补码相加就不会产生问题因为5位二进制补码可以表示的十进制数范围是-16到15。具体过程为0010000100得到01000即8的二进制补码。在计算机中使用了OF这个标志来表示在当前的数据和当前选择的补码位宽的情况下是否会产生溢出它的产生可以使用多种判定条件。1、当SaSb且Ss!Sa即两个加数符号相同且结果与两个加数符号不同OF置1。2、当符号位相加的进位不等于最高有效位相加的进位时OF置1这也很好理解当最高有效位有进位时如果符号位没有进位表示符号位都为0此时两个符号位为0的数相加得到了符号位为1的结果当最高有效位没有进位如果符号位有进位表示符号位都为1此时两个符号位为1的数相加得到了符号位为0的结果。上面已经讨论完了有符号数相加的情况当有符号数相减时使用的其实依然是最初的补码运算公式但此时进行了一些变形。在这个步骤中只要把y换成y相反数的补码即可通过一个数的补码可以很容易地得到其相反数的补码将其所有二进制位取反加一即可包括符号位此处注意虽然最小的那个负数取反加一后仍然是自己但依然不影响结果的正确性例如对于十进制数5的4位二进制补码0101十进制数-5的二进制数补码即为1011。这样就将所有的减法转换为了加法这正是补码运算的强大之处。下面我们来谈一下无符号数的加减法无符号数不包括符号位但依然可以按照补码的方式加减我们只需要给他添上一位符号位0表示其为正数即可即对于十进制数8的4位无符号二进制数1000在运算时可以将其看做5位二进制补码01000其中首位0为符号位。此时两个无符号数的加法可以看做两个有符号正数相加若结果的符号位为则1代表有进位就像有符号数相加产生溢出一样进位用CF表示但这里只会出现正数相加溢出。当两个无符号数相减时就把减数按照有符号数相减中方式一样变成其相反数的补码然后相加此时若结果的符号位为0最高有效位有进位则表示没有借位若符号位为1最高有效位无进位则表示有借位即相减结果为负借位也用CF表示就像是两个有符号正数相减一样。比如若相减结果为10111可以看做结果是7并有借位也可以看做相减结果为-9。从上面的讨论中我们得到了一个结论在计算机中无论是有符号数加减还是无符号数加减都是用补码加法实现的。