《计算机系统:核心概念及软硬件实现(原书第4版)》——3.2补码二进制表示...

本节书摘来自华章计算机《计算机系统:核心概念及软硬件实现(原书第4版)》一书中的第3章,第3.2节,作者:[美] J. 斯坦利·沃法德(J. Stanley Warford)著, 更多章节内容可以访问云栖社区“华章计算机”公众号查看。

3.2补码二进制表示

无符号二进制表示法仅适用于非负整数。如果计算机要处理负整数,那么它必须要用一种不同的表示法。

image


假设有一个6位的单元要存储-5(dec)。因为5(dec)是101(bin),所以你可能想到图3-7所示的样子。但这是不可能的,因为所有的位必须是0或1。谨记计算机是二进制的。上面这种存储值要求每个方框可以存储0或1或破折号,这样的计算机必须是三进制而不是二进制。

image


解决这个问题的办法是保留单元的第一个方框来表示符号。这样,6位单元将分为两个部分—1位符号位和5位数值位,如图3-8所示。因为符号位必须是0或1,所以一种可能是让符号位0表示正数,符号位1表示负数。那么+5可以表示为:
00 0101
-5可以用表示为:
10 0101
在这种表示法中,+5和-5的数值位是相同的,仅仅是符号位不同。
然而,很少有计算机用前面这种代码,因为如果进行十进制的+5加-5,得到0,但如果进行二进制的00 0101加10 0101(符号位和所有),得到
image

这显然不等于0。如果CPU硬件可以用无符号二进制加法的普通算法对包含符号位的完整数字+5和-5进行相加并得到0,这会更加方便。
补码(two抯 complement)二进制表示有这个特性,正数由符号位0和与无符号二进制表示一样的数值位组成。例如,十进制+5(dec)仍然表示为00 0101。
但是-5(dec)的表示不是10 0101,而是11 1011,因为+5加-5是
image

注意6位的和都是0,和我们期望的一样。
按照6位单元的二进制加法法则,11 1011称为00 0101的加法逆元(additive reverse)。求加法逆元的运算称为求补(negation),缩写为NEG。对一个数求补也称为取它的补码。
现在我们所需的是求一个数补码的法则。有个简单的法则是基于反码(ones抍omplement),反码是把所有的1变为0,0变为1的二进制序列。反码也称为NOT运算。
例3.8 假设一个6位单元,00 0101的反码是
NOT 00 0101=11 1010 □
找出补码规则的线索是把一个数和它的二进制反码相加的结果。因为1加0等于1,0加1等于1,所以任意数和它的反码相加将生成一个全1的序列,然而把一个单独的1和全1的数相加就会得到一个全0的数。
例3.900 0101加上它的反码
image

这个数是全0的。 □
换句话说,把一个数加上它的反码,再加1就得到全0的数,因此一个数的反码加1一定是它的补码。
例3.10将00 0101的反码加1得到它的补码。
image

00 0101的补码是11 1011,即,
NEG 00 0101 = 11 1011
11 1011的确是00 0101的负数,因为如前所示两者相加为0。 □
不管一个数有多少位,对一个数求补的一般法则是:
一个数的补码等于它的反码加1。
或者用NEG和NOT运算表示为
NEG x=1 + NOT x
在我们熟悉的十进制中,如果对一个负数值取负,那么将得到一个正值,代数表达式为
-(-x)=x
这里x为正值。如果求补码的法则是有效的,那么一个负数值的补码应该是相应的正值。
例3.11如果对-5(dec)取补码会怎样?
image

瞧!如你所期望的,又得到了+5(dec)。 □
3.2.1补码的表数范围
假定有一个4位单元以补码形式存储整数,那么这个单元能表示的整数范围是多少?
数值最大的正整数是0111(bin),即+7(dec)。这和在无符号二进制数中最大值为1111不同,因为第一位被保留作为符号位且一定是0。在无符号二进制中,用4位单元可以存储的最大数是+15(dec),所有4位都用于存储数值。在补码表示中,能存储的最大数只是+7(dec),因为仅有3位用于数值。

image


数值最大的负整数是什么呢?这个问题的答案可能不太显而易见。图3-9展示了最大到7的每个正整数的补码,在图中看到了什么规律没有?
我们注意到补码运算自动在负整数的符号位生成了一个1,它本来就应该这样。偶数仍然以0结尾,奇数仍然以1结尾。

image


而且,如你所期望的,二进制-6加1得到-5,类似地,二进制-7加1得到-6。我们可以从4位挤出一个更大的负整数-8。二进制-8加1得到-7,因此-8应该用1000表示。图3-10是一个4位存储单元的完整有符号整数表。
-8(dec)有一个其他负整数没有的属性,如果取-7的补码会得到+7,如下所示:
image

但如果取-8的补码,得到的还是-8:
image

因为4位无法表示+8。
我们已经确定了4位单元的补码二进制表数范围以二进制表达是1000到0111,或者以十进制表达是-8到+7。
不管单元包含多少位,模式都是一样的。最大的正整数是一个0后面全是1,而数值最大的负整数是一个1后面全是0,它的数值比最大正整数大1。-1(dec)用全1表示。
例3.126位补码表示的表数范围,用二进制表示是
10 0000到01 1111
或者十进制表示是
-32到31
和其他的负整数不同,10 0000的补码就是它自己10 0000。还可以看到-1(dec)= 11 1111(bin)。 □
3.2.2基数转换
把一个负数从十进制转换为二进制分为两步。首先,把它的数值部分当作无符号表示转换为二进制;其次,按照补码的方式对它取反。
例3.13对于10位单元的-7(dec)
image

因此-7(dec)的补码是11 1111 1001(bin)。 □
在采用补码表示的计算机中,把一个数从二进制转换成十进制,总是首先检测符号位。如果是0,这个数是正数,可以按照无符号数表示进行转换;如果是1,这个数是负数,可选的方法有两种。一种是通过取反得到正数,然后再按照无符号数的法则,把它转换成十进制。
例3.14一个10位单元的内容为11 1101 1010,它代表的十进制数是什么?符号位是1,因此这个数是负数,首先对这个数取反:
image

因此原始的二进制数一定是38的负值,即
11 1101 1010(bin)=-38(dec) □
另一种方法是不用取补码,直接转换,即只用在原始二进制数中为0的那些位的位置值相加,再加1。这个方法是正确的,因为取正整数补码的第一步就是按位取反。那些本来对正整数数值有贡献的1变为了0,所以是0而不是1对负整数的数值有贡献。

image


例3.15图3-11显示的是11 1101 1010(bin)的为0的位置 ,把这些位的位置值之和加1得到
1101 1010(bin)=-(1 + 32 + 4 + 1)=-38(dec)
这和前面方法得到的结果是一样的。    □
3.2.3 数轴
看待二进制表示的另一种方法是使用数轴。图3-12展示了3位单元的无符号二进制表示的数轴,能够表示8个数字。

image


可以通过在数轴上往右移动进行加法运算。例如,4加3,从4开始往右移动3个位置得到7。如果尝试在数轴上6加3,将超出最右端。如果用二进制进行这个加法,将得到不正确的结果,因为结果超出了范围:
image

把无符号数轴在3和4之间断开,把右半部分移到左边,这样可以得到补码的数轴。图3-13显示了二进制数111现在和000相邻,之前是+7(dec),现在是-1(dec)。

image


即使有经过0,加法仍然是通过在数轴上向右移动来进行的。-2加3,从-2开始向右移动3个位置得到1。如果用二进制计算,答案在范围内,因此是正确的:
image

这些位和无符号二进制6加3是一样的。我们注意到结果虽然在表数范围内,但是进位位是1。在补码表示中,进位位不再表示加法的结果是否是在范围内。
有时候,只考虑移动后的十进制数轴,可以完全避免二进制表示。图3-14展示了补码数轴,用等值的无符号十进制数代替二进制数。这个例子中,每个存储位置有3位,因此最多有23或8个数。


image


现在,从0到3的无符号数与有符号数是一样的。此外,通过减8可以从无符号数得到有符号负数:
7-8=-1
6-8=-2
5-8=-3
4-8=-4
例3.16假定有一个8位单元,有28或256个可能的整数值,非负数从0到127。假设采用补码表示,97加45等于多少?以无符号二进制数计算,和等于
97 + 45=142(dec,unsigned)
但用在补码表示中,这个和为
142 - 256=-114(dec,signed)
注意,这样的结果完全避免了二进制表示。为了验证结果,首先把97和45转换为二进制并相加:
image

符号位是1,因此这是一个负数。现在,确定它的数值大小
NEG 1000 1110=0111 0010 (bin)

            =114(dec)               □

得出预期的结果。
3.2.4溢出位
在ISA3层上二进制存储的一个重要特性就是每个值都没有与之相关的类型。在前面的例子中,和1000 1110,作为无符号数解释时,它是142(dec),但作为补码表示解释时,它就是-114(dec)。尽管位模式的值取决于它的类型,是无符号还是补码,但是硬件对两种类型不加以区分,只存储位模式。
当CPU对两个存储单元的内容相加时,它不管它们的类型,只采用位序列上的二进制加法法则。对于无符号二进制,如果和超出表数范围,硬件只是简单存储(不正确的)结果,相应地设置C位并继续往下走。由软件来检测相加后的C位,看是否在最高位的那一列有进位发生,并按需采取适当的动作。
我们前面说过,在补码二进制表示中,进位位不再表示一个和是否在表数范围内。当运算结果超出表数范围时,我们称为出现了溢出情况(overflow condition)。为了为有符号数标示这种情况,CPU中有另一个用V表示的特殊位,叫作溢出位(overflow bit)。当CPU对两个二进制整数相加时,如果和超出补码表示的范围,那么V设置为1,否则V设置为0。
不论以何种方式解读位模式,CPU总是执行同样的加法运算。与C位一样,如果发生了补码溢出,CPU不会停下来,它将V位设置为1,并继续它的下一步工作。由软件来检测加法后的V位。
例3.17这里有几个6位单元的例子,展示了进位位和V位的情况:
image

注意V和C的值有可能是所有的组合。 □
怎样才能知道发生了溢出情况呢?一种方法是把两个数转换到十进制,两者相加看它们的和是否超出了以十进制表示的范围。如果是,那就是发生了溢出。
硬件通过将符号位的进位与C位比较来检测是否溢出发生:如果两者不同,溢出发生,V为1;如果两者相同,V为0。
不将符号位的进位与C位比较,也可以通过查看加数与和的符号,直接确定是否发生了溢出。如果两个正数相加得到负数或者两个负数相加得到正数,那么就发生了溢出;一个正数和一个负数相加是不可能发生溢出的。
3.2.5负数和零位
除了检测无符号整数溢出情况的C位和检测有符号整数溢出情况的V位外,CPU还维护了另外两位,供软件在运算后进行检测。它们是N位和Z位:N位用于检测负数结果,Z位用于检测零结果。总的来说,这4个状态位的函数是
N=1,如果结果是负数。
N=0,其他情况。
Z=1,如果结果全是零。
Z=0,其他情况。
V=1,如果有符号整数溢出发生。
V=0,其他情况。
C=1,如果无符号整数溢出发生。
C=0,其他情况。
由于N位是符号位的一个副本,所以硬件很容易确定它。而要确定Z位,硬件则要费点儿工夫,因为它必须确定结果的每个位是否都为0。第10章展示了硬件怎样根据结果计算状态位。
例3.18这里有三个加法例子,展示了结果的4个状态位情况。
image

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值