浅析补码之美

2021.07.26

教育教学论坛

一、引言

计算机组成原理这门课程所涉及的概念多且抽象,课堂上学生通常感觉知识点会扑面而来、枯燥和难接受。课堂教学一方面是知识点的讲授,另一方面更需要引导学生去探究问题,感受学习的乐趣,激发他们内在的学习积极性。但事实上,当转换视角后,总能看到人类智慧在熠熠发光。

如果说引入二进制让计算机有长足的发展,那么补码的引入应该也可以算一个,因为它使得计算机在进行运算时的实现电路变得简单。计算机中的有符号数表示最常见的是补码[1],对计算机专业的学生来讲,补码在较早的课程中已接触,当问及补码的作用时,都知道补码可以将减法变成加法,再进一步发问:为什么要这么做?为什么补码可以实现?它是如何实现的?却常出现静音的情况。发问后他们似乎才发现,对啊,它是如何将减法变成加法的呢?此外,补码在计算机中还有别的用处吗?

比如,机器数中的正负号用01表示,此时的01只表示正负两种状态,没有大小之分,它能不能与数据位的01序列一同参与运算(或者说,计算机需不需要将符号位与数值位区别对待)?如果不能,那如何处理?如果能,那参与运算意味着是有大小之分,运算后需不需要对符号位或运算结果做后续处理呢?等等一系列的问题。下面就上述问题从补码的引入开始讨论。

二、补码的引入

原码表示数据简单直接,易求真值,但当两个符号相异的数相加时[2],如5+-4),需要做的运算实际上是先判断两个数的绝对值大小,然后用绝对值大的减去绝对值小的,最后再将绝对值大的那个数据的符号作为结果的符号。这样已然是将加法变成了减法,运算复杂了!如果要求只做加法,怎么办?一个自然的想法就是找到一个与负数等价的正数。

与负数等价的正数,这个概念可在生活中随处找到相应的例子。比如,家里的燃气表,试想,此时的表盘中整数区域显示的数字全是9,当使用燃气让小数产生进位时,整数部分的数字将变成全0,即99999+1=00000,而在算术运算中,-1+1=0,故,与-1等价的正数找到,是99999。找一个与负数等价的正数,此想法可行!

当然,这里的等价是有前提的:数据的位数受到限制。本例中的位数是5位,其模为100000,故99999-1等价。另外,这个概念在钟表中也有例证[2],钟表的模为12。若时钟指示为1点,欲使其指向6点,可以顺时针拨动分针5圈,也可以逆时针拨动分针7圈,若设顺时针拨动为正,逆时针为负,那么+5≡-7(称该正数即为负数的补数)。即,在模为12的情况下,5+(-4≡5813-12(模)=1,读者可自行以此类推。而任何一台计算机都是位数受限的!因此,找一个与负数等价的正数,在计算机中也可行!

细心的读者会发现,这里只是说明用补数实现了与负数等价的正数,但与补码有所不同:负数补码的符号位为1,即从表面上看应该是一个负数,问题在哪呢?这,也正是后面要讨论的补码情况下符号位参与运算却不需要修正之美的关键!那么,借用表盘来进一步说明,将顺时拨动分针设为加法操作,将逆时针拨动分针设为减法操作,如果此表只能顺时拨动分针,也即只能进行加法操作。若想做4-5的运算时,顺时针拨动分针7圈(-5≡7),即到11点,与算术运算结果为-1不能直接对应。众所周知,算术运算的结果是有符号数,而表中的数字是无符号数,因此,需要将表盘数字重新标识,以12(或0)为界,顺时针方向正的一半为0~5,逆时针方向由大到小负的一半为-1~-6,那么刚才的运算结果即为-1。由此也说明正数的补码是其本身,同时也可看出补码的表示范围,在模为12的情况是-6~5,在数值上是不对称的。

若将此概念换成二进制,假设有4位二进制数,即模为16,无符号数为0000~1111,有符号数时,即为正的为0000~01110~7),负的为1111~1000-1~-8[附记])。

此为补码之美的第一个表现:将减法变成加法。

三、求补(或变补)之美

用补码进行减法运算时,其运算公式为(X-Y)=X+-Y,通常把由Y到(-Y的过程称为求补操作或变补操作,即已知一个数的补码求其相反数的补码。

在实现求补操作时[2],已知Yy0.y1y2y3…yn,其中y0是符号位,Y分正、负数两种情况,当Y为正数时,即y00Y0.y1y2y3…yn,其原码为Y0.y1y2y3…yn,相反数为-Y=-0.y1y2y3…yn,在此基础上求(-Y1.y_1y_2y_3y_n2-n,对比Y和(-Y,可知对正数进行变补操作是连同符号位在内按位取反,末位加1。  

Y为负数时,即y01Y1.y1y2y3…yn,其原码为Y1.y_1y_2y_3y_n2-n=-(0.y_1y_2y_3y_n2-n),相反数为-Y0.y_1y_2y_3y_n2-n,得到相反数的补码为:(-Y0.y_1y_2y_3y_n2-n,对比Y和(-Y,可以看到,对负数进行变补操作也是连同符号位在内按位取反,末位加1

故:在求补的操作中,计算机不用关心输入数据是正还是负,并且将其同符号位与数值位一起按位取反末位加1。即,符号位与数值位一起参与操作,且结果不需要做任何处理,此为补码之美的第二个表现。

四、补码的加减之美

下面通过几个简单的例子来看补码的加减之美。例子中采用1个符号位,4个数值位,在原码加法中,两数同符号时均做加的操作,两数异号时则实际做的是减法操作,这里以两数的符号位相异的情况来说明,第一个例子6+-5=0 0110+1 1011(补码),两数相加且符号位也参与运算,符号位向前的进位自动扔掉,结果为0 0001,正确;第二个例子:(-6+5=1 1010+0 0101,结果为1 1111,它是-1的补码,符号位也参与运算。由此可见,操作码为时,两数直接相加,符号位参与运算,结果也是补码表示的数值,不需要做任何修正处理,满足:( X + Y )= X + Y   

下面是减法的例子,第一个7--5=0 0111+0 0101-5=1 0101(原码)=1 1011(补码) ,对(-5)的补码求补为0 0101,结果为0 1100=12,正确;第二个(-7-5 =1 1001+1 10115d=0 0101(原、补码),对它求补得:1 1011,相加,符号位的进拉自动扔掉,得1 0100(补码),其真值为-12

可见,操作码为时,将减数变补后与被减数相加,符号位同样也参与运算,结果也是补码表示的数值,不需要做任何修正处理,满足:( X - Y ) = X + (-Y)  

     故:在补码表示的情况下,无需区分正负数,符号位参与运算,且运算结果不需要做任何修正。此为补码之美的第三个表现。也正因如此,采用补码对有符号数进行加减运算的电路,也可用于无符号数的运算,如此以来,可简化CPUMPU的电路设计和相应的软件设计[3,4]

五、补码的算术移位之美

移位运算对计算机有很大的实用价值,在当计算机中没有专门的乘除法运算线路时,可以将移位与加法结合实现乘除运算。

计算机中机器数的字长通常是固定的,当机器数向左移或右移时,必然会使其低位或高位出现空位,针对有符号数的移位称为算术移位,移位时其符号位保持不变。对正数而言,无论是原码还是补码,也不管左移还是右移,移位后出现的空位均添0;但是对于负数则不同,原码的左右移时空位均添0;补码左移时空位添0,右移的空位添1[2]

     从直观感觉上来讲,补码的移位规则比原码麻烦,补码需要区分正负数,且负数左右移还不同。但细看它们的左、右移电路实现原理示意图,情况就会发生变化。

从图1[2]横向看,第一排原码和补码的左移都是一样的;正数的原码和补码左右移如(a)图所示;原码负数的左右移均添0,右移如()图下图所示,明显与(a)图下图不同;但是对于补码而言,负数右移示意图如(c)图中的下图所示,与(a)图一样。即:补码无需区分正负数。

故:在补码表示的情况下,无论正数还是负数,其算术移位为同一电路,此为补码之美的第四个表现。

六、结语

计算机中采用补码表示有符号数,在异号相加的情形下,补码表示可以将减法变成加法,而且符号位连同数值位一起参与运算,运算结果也不需要进行任何后续处理;在做减法运算时将减数进行的变补操作因采用补码而变得简单。同时,数据采用补码表示的实现电路对有符号数和无符号数均可运算。另外,在算术移位操作中,也因补码的引入使得电路设计变得简单,不由为补码设计之美妙发出由衷的感叹!