2.1.3(拓展)各种码的作用
*文章整理自王道公开课程《王道计算机考研 计算机组成原理》,文中时间节点与本节课程视频相对应。
课程重点详细勾画请WX搜索GZH:玄默冲虚
00:01
好的,上个小节中我们学习了定点数的原码、反码、补码和移码表示。这个小节中我们要着重探讨的是这些各种码它们有什么缺陷和作用。我们从一个加减运算的例子出发,假设现在有一个字长机器,字长为八比特的计算机,有这样的两串二进制数据。那么我们对这两个二进制数据进行一个加法运算。0加0等于0,一加一等于0,高位进1 1加1再加一等于一再往高位进一。用这样的方式我们可以得到这两个二进制数的一个相加结果。
00:41
如果说这两个二进制数它们表示的原本表示的是一个无符号数的话,上面这个数应该是2加4加8,应该是等于14。而下面这个数大家可以你算一下,应该是等于142这样的一个增值。14加142应该是等于156和我们最终得到的这个运算结果是一致的。
01:06
但是如果这两个二进制数它们是用原码表示的有符号数的话,那看一下最高位是符号,这是一个正的数,下面一个是负的数。而这两个数的尾数都相同,都是14,所以上边这个数。如果它是原码的话,应该是正十四,下边是-14。正14加-14本来是应该等于零的。然而我们这儿用这种加法运算的规则算出来的结果却不是零。所以这就意味着当我们对原码进行加减运算的时候,如果说是一个正数加上一个负数,那么我们需要把这个运算把它改造成一个正数减掉另一个正数这样的方式,也就是14减14。那么我们把-14的这个符号位把它换为零,也就是换为正14。那么两个数一相减得到的结果是零,这样的话就可以得到一个正确的结果。
02:08
所以从这个例子中我们可以体会到,计算机硬件对原码进行加减运算的时候,必须考虑到符号位。当符号位为零或者为一的时候,可能需要硬件自动的对这个加减运算做出一些调整。另外在算术逻辑单元当中,还必须拥有一个加法器和一个减法器。加法器的硬件电路设计起来其实是相对容易的,但是要用硬件实现减法,这个硬件电路设计起来就困难得多。所以硬件既要实现加法功能,也要实现减法功能,就会导致硬件的设计成本增加,同时复杂度也增加。这个时候就有一帮很聪明的人想到了一个方法,就是想我们能不能用加法运算来代替减法运算。
02:59
好,来看一下怎么实现。我们从大家熟悉的十进制的例子出发。现在这儿这是一个时钟,它指向了十点的方向。假设你现在想把这个时钟调到七点的话,那么我们是不是有两种方式。第一种方式你可以选择逆时针的来调。
03:19
由于需要调一格两格,三格需要调三格,而逆时针我们把它看作是减法,所以这就相当于是10减3等于七这样的一个操作。另一种方法是我们可以顺时针的调,同时这往右调九格同样也可以达到七这样的一个位置。如果结合之前的逻辑来解释,逆时针调整我们把它看做减法顺时针调整我们把它看作加法。所以下边这种方式我们相当于是10加9,本来应该等于19的,但是由于我们的时钟盘面它只有12个数字,所以我们最终时钟的指向其实是要用19来对12进行一个除法。然后得到的余数7就是我们最终这个时钟的指向。
04:10
在我们做完加法之后,是做了一个取余数的一个运算。那在数论当中这种取余的操作,我们通常会把它称为模运算。就是19对10二取模等于72,就是所谓的模。其实这个运算就是我们取余数的一个运算。
04:31
好,所以这个例子想要说明的一点是在我们模12的条件下,其实一个减法操作,我们可以把它转换为一种与之等价的加法操作。我们可以说负三这个数和9这个数,在模12的条件下,它们俩是完全等价的,可以相互替换。它们俩等价的意思是说-3对12取余,或者说对十二取模,它的余数其实也是等于9。而9对12取模余数同样等于9。
05:07
那大家可能比较疑惑的是,负数对十二取余这个怎么计算?在数论中对余数的定义是这样的,对于一个数XX对M取模或者对M取余,这个余数到底等于多少呢?这个余数R应该满足这样的一个式子。我们需要找到一个整数Q,Q乘以M再加上一个大于等于零且小于M就是小于模数的一个整数。那如果R满足这个式子,那它就是X对M取模的一个余数。
05:41
像刚才那个负数的例子中,负三模12,它的余数R应该是等于多少?我们带入这个式子来看一下,负三应该是等于负一,也就是这个Q乘以模数12,然后再加上一个加上一个九。因为这儿的R必须大于等于0,并且小于12,所以我们只能找到这样的一个式子,满足我们这儿对余数的定义。因此-3模12它的余数应该是等于9,而9模12的余数,这个很简单,九应该是等于0乘以12再加上9,所以它的余数就是9。好,因此我们从这个余数的定义就可以知道,负三它模十二应该是等于99,磨12也等于9,二十一磨12也等于9,33-15这些数,它们磨12都是余9,所以我们可以说在模12的条件下,-39、21、33还有-15这些数,他们就是完全等价的。在进行运算的时候,我们可以用这些数来进行互相的替换,可以看到所有这些数之间相差刚好就是12,-3加12等于9,然后九再加十二等于21,21再加十2等于33,然后负三如果减掉一个12的话是等于15。
07:13
好,这个应该很好理解。那在模12的这种条件下,对于任意一个整数是不是有可能得到的余数R应该是012一直到11,总共有12种有可能能出现的余数,对吧?所以其实所谓的模运算模12的这个条件是把所有的整数分为了12类,也就是余数分别为零一直到11这样的12类。而刚才我们举的这个例子当中,所有的这些整数都属于同一类。因为它们模式二的余数都等于9。那么对于这种余数相同的数,我们就把它们看作是同一类,都是等价的。
07:53
好,那我们再来结合刚才调时中的例子看一下,十点往逆时针调了三格,也就十加上负三这个加法操作。我们可以用负三的一个等价的数来进行一个替换。负三和9是等价的,所以10加负三等价于10加9。
08:15
当然在进行这个加法运算之后,我们同样还要进行一个模十二的这个运算。那十九在模十二之后是不是又等于七好?除了九之外,我们还可以用等价的21来替换-3。那10加21应该是等于31,大家可以算一下,31模10 2同样应该是等于七,好。所以在模式12的条件下,所有的整数被分为了总共12个种类。属于同一类的这些数,我们都把它们看作是等效等价的。这些等价的数在进行加减运算的时候,可以进行相互的替换,最终得到的效果是相同的。
08:57
所以回到我们刚开始提出的问题,我们想要用加法来代替减法,其实是可以实现的。比如在模式二的情况下,减3就可以用加九来代替。由于-3和9这2个数在模式二的条件下它们等价,另外它们俩的绝对值相加刚好等于模数12,所以这两个数我们把它称为互为补数。一对补数它们的绝对值之和要等于模,显然这一对补数它们的绝对值都是要小于我们的模的。好,所以对于一个减法运算,如果我们能够把这个负数找到与之互补的另一个数,那么我们是不是就可以把一个减法操作用加法操作来等价的替换了。刚才我们说过两个互补的数,它们的绝对值相加应该是等于模。所以我们只需要用模的值,减掉这个负数的绝对值,就可以得到这个负数它所对应的补数。这个补数是一个正数,这样我们就可以用正数的加法来替代减法了。
10:10
好,回到之前的加减运算,我们这儿用14减掉14。现在我们想要用加法来替代这个减法,那我们只需要找到-14的1个补数就可以,在这儿。我们假定计算机的机器字长是八个比特,也就是说这台计算机它只能表示八个全0到8个全一这样的一个范围,也就是0到2的8次方减1这样的一个范围的数。所以当加法运算超出这个范围的时候,其实计算机只会保留最低的八位。那这个操作就相当于计算机的硬件天然的完成了模二的8次方这样的一个运算。因为刚才我们说过,模十二是不是相当于把所有的整数全部映射到了0到11这个个范围。那模2的8次方是不是就相当于把所有的整数全部映射到了0到2的8次方减一这样的一个范围。所以计算机硬件的特性天然的就规定了我们所有的这些加减运算,其实都应该把它看作是模二的8次方这样的一个条件下进行的。
11:20
好,所以我们现在已经确定了模应该是2的8次方。那么要确定-14它的一个补数,是不是就用模来减掉这个-14的绝对值,然后就可以得到它的补数。那这儿我们得到-14的补数应该是这样的一个值。其实就是上个小节学习的-14的补码。
11:44
我们用上个小节学习的方法来尝试着转换一下,这是-14的原码。首先需要把所有的尾数取反,然后末尾再加一个1,那最终得到的就应该是11110010,和我们这儿算出结果是相同的。其实用模减掉这个负数的绝对值,这个才是补码的原生的定义。
12:14
好,现在我们已经得到了-14在模2的8次方这个条件下的一个补数。我们用补数的加法来替代原先的这个减法,得到的结果应该是这样的,最终会往高位进一个一。但是我们之前说过,这台计算机只有八个比特的机器字长,也就是说最高位会被天然的抛弃,硬件天然的帮我们完成了模二的8次方这样的一个处理,所以最终留下的这八个位全部为零,刚好转换成十进制也对应0。那-14减14等于零是不是就得到了正确的结果?
12:54
好,所以这就是上个小节学习的补码的一个作用。我们可以用补码让减法操作转变为等价的加法操作。这样的话我们在ARU算是逻辑单元里边,我们只需要设计加法相关的电路,而不需要设计减法电路。这样的话硬件成本就可以大大降低。
13:17
好,我们结合这个补码的定义来看一下,为什么我们补码的求法是尾数取反,然后末尾加1。对于一个负数,比如说这儿的-14来说,它的绝对值应该是00001110,这是-14的绝对值。那-14的绝对值加上它的补数,也就是它的补码应该是要等于模,也就是等于一个18个02的8次方这样的一个值。好,那它的补码应该是多少呢?如果我们把负十四它的绝对值全部取反,所有的位都取反,那就会变成111100001。那这两个数它们相加是不是刚好可以得到一个八位全为一的一个数?那在这个基础上,如果我们再在末尾再加一个一,也就刚才我们加上的这个数,我们再让它加一个一。这样的话这两个数相加是不是刚好就可以得到一个1,8个0,对吧?
14:23
所以为什么我们通过一个原码来求补码的时候,是符号位不变。然后后续的这些位全部取反再加一,就是这个原因。这个我们结合补码的定义就可以理解。当然了如果用数学手段很严谨的解释清楚补码的原理,这个我们还需要很多数论的知识,这就不再展开,大家也不需要深究。这儿给大家讲这些只是为了让大家知道补码的一个作用,还有它为什么能呈现出这样的作用,大家能够知道个大概就可以了。
14:56
好,我们再看一个利用补码把减法变加法的一个例子。88减66,这已经给出了他们的一个二进制表示。现在我们要用加法替代减法,也就是要找到-66的一个补数它的补码那它的补码应该是模二的8次方减掉66的绝对值,那这样我们就得到了它的补码或者说它的补数。然后这两个数一相加应该是等于这样的一个值。我们把高位的一给舍弃,后边留下来的这八位,它的值应该是这个是24 86,应该是16加4再加2,等于十进制的22,这就是88减66的一个正确结果。总之我们补码的作用就是可以把减法操作转变成等价的加法。这样的话ARU当中就不需要再集成减法器,可以让硬件成本下降。另外当我们在执行加法操作的时候,大家会发现符号位也会一起参与运算。
16:05
想要深究为什么的同学可以去研究一下数论。数论是计算机世界里边很强大的一个数学工具。计算机里边的很多编码方案,还有什么密码学之类的,都是基于数论作为一个数学基础。有兴趣的同学自己可以去研究一下。
16:23
好,这是补码的作用。这儿我们留下一个坑,刚才我们进行这个补码的加法运算的时候,产生了一个进位,这个进位被我们丢弃了。但有的时候这个进位的信息会反映出我们的运算是否产生了溢出。比如大家可以算一下-100加上-100用补码运算,那显然是会产生溢出的那溢出应该怎么判断?这个问题我们留在之后的小节再来探讨。好的,这是补码。
16:52
最后我们再来看一下移码,其实移码的作用上一小节我们已经说清楚了。由于真值的递增和移码的绝对值的递增是完全一致的。所以如果用移码来判断两个真值谁大谁小的话,那用硬件来实现这个逻辑是很方便的。所以移码的作用就是方便对比大小。
17:13
好的,这小节中我们探讨了原码补码和移码的一个作用。反码的话就不需要探讨,因为反码只是原码转变成移码的一个中间状态。原码的作用自然不必多说,它很符合我们对于二进制数的一个理解。但是如果使用原码,要实现减法运算,必须使用一个专门的减法器这样的硬件来实现,会导致硬件成本的上升。那解决的方法就是用补码的方式把减法转变成加法运算。其实就是要找到一个负数的补数,这样的话计算机硬件的成本就可以大幅降低。最后这个移码的作用就是可以很方便的让我们用硬件电路来比较两个数的大小。好的,以上就是这一小节的全部内容。