第二章 数据的表示和运算
2.1 数制与编码
2.1.1 进位计数制及其相互转换
1.进位计数法
在进位计数制中,每个数位所用到的不同数码的个数称为基数。十进制的基数为10(0~9)。
每个数码所表示的数值等于该数码本身乘以一个与它所在数位有关的常数,这个常数称为位权。
可以用后缀字母标识一个数的进位计数制,用B表示二进制数,用O表示八进制数,用D表
示十进制数(通常直接省略),用H表示十六进制数,有时也用前缀0x表示十六进制数。
2.不同进制数之间的相互转换
(1)二进制数转换为八进制数和十六进制数
对于一个二进制小数(既包含整数部分,又包含小数部分),在转换时应以小数点为界。其
整数部分,从小数点开始往左数,将一串二进制数分为3位(八进制)一组或4位(十六进制)
一组,在数的最左边可根据需要加“0”补齐;
对于小数部分,从小数点开始往右数,也将一串二进制数分为3位一组或4位一组,在数的最右边也可根据需要加“0”补齐。
最终使总的位数为3或4的整数倍,然后分别用对应的八进制数或十六进制数取代。
同样,由八进制数或十六进制数转换为二进制数,只需将每位改为3位或4位二进制数即可(必要时去掉整数最高位或小数最低位的0)。
八进制数和十六进制数之间的转换也能方便地实现,十六进制数转换为八进制数(或八进制数转换为十六进制数)时,先将十六进制(八进制)数转换为二进制数,然后由二进制数转换为八进制(十六进制)数较方便。
(2)任意进制数转换为十进制数
将任意进制数的各位数码与它们的权值相乘,再把乘积相加,就得到了一个十进制数。这种
方法称为按权展开相加法。
(3)十进制数转换为任意进制数
对整数部分采用除基取余法,对小数部分采用乘基取整法,
最后将整数部分与小数部分的转换结果拼接起来。
除基取余法(整数部分):整数部分除基取余,最先取得的余数为数的最低位,最后取得的
余数为数的最高位(除基取余,先余为低,后余为高),商为0时结束。
乘基取整法(小数部分):小数部分乘基取整,最先取得的整数为数的最高位,最后取得的
整数为数的最低位(乘基取整,先整为高,后整为低),乘积为1.0(或满足精度要求)时结束。
2.1.2定点数的编码表示
1.真值和机器数
这种带“+”或“-”符号的数称为真值。真值是机器数所代表的实际值。
在计算机中,通常将数的符号和数值部分一起编码,将数据的符号数字化,通常用“0”表示“正”,用“1”表示“负”。这种把符号“数字化”的数称为机器数。常用的有原码、补码和反码表示法。
2.机器数的定点表示
(1)定点小数
定点小数是纯小数,约定小数点位置在符号位之后、有效数值部分最高位之前。
(2)定点整数
定点整数是纯整数,约定小数点位置在有效数值部分最低位之后。
事实上,在机器内部并没有小数点,只是人为约定了小数点的位置。因此,在定点数的编码和运算中不用考虑对应的定点数是小数还是整数,而只需关心它们的符号位和数值位即可。
定点数的编码表示法主要有以下4种:原码、补码、反码和移码。
3.原码、补码、反码、移码
(1)原码表示法
用机器数的最高位表示数的符号,其余各位表示数的绝对值。
注意:字长代表符号位和数值位的位数。
字长一般定为n+1位,其中n位为真值的位数,1位为符号位。
负数的原码表示:
2的n次幂-x = 1,000 0000-(-1110)= 1,000 1110
减去一个负数相当于加上一个正数,两种负数的原码表示是一致的。
2的n次幂+x的绝对值 = 1,000 0000+1110 = 1,000 1110
原码所表示范围:
2的n次幂为1,000 0000,正数原码的最大值0,111 1111 刚好小于2的n次幂
-2的n次幂为-1,000 0000 同样类似的,负数原码的最小值0,111 1111 刚好大于-2的n次幂
若字长为n+1,则原码整数的表示范围为-(2的n次幂-1)<=x<=2的n次幂-1(关于原点对称)。
(2)补码表示法
补码表示法中的加减运算统一采用加法操作实现。
正数的补码和原码相同,
负数的补码等于模(n+1位补码的模为2的n+1次幂)与该负数绝对值之差。补码的定义如下:
正数的补码表示:
0,真值
2的n+1次幂+x=10,000 0000+1010=10,000 1010
保留8位字长后为0,000 1010
负数的补码表示:
2的n+1次幂+x=10,000 0000+(-1101)=01,111 0011=1,111 0011
和原码的负数表示同样理解。
2的n+1次幂-x的绝对值=10,000 0000-1101=01,111 0011=1,111 0011
快捷求负数的补码:
1.符号位不变,数值位各位取反,末位加1
2.符号位不变,从右向左数第一个1,其左侧均各位取反
补码所表示的范围:
2的n次幂为1,000 0000,正数补码的最大值0,111 1111 刚好小于2的n次幂
负数范围,因为0,000 0000按位取反+1之后是0,111 1111+1=1,000 0000=2的n次幂,所以负数的表示范围可以取到2的n次幂。实际上按位取反再加1之后补码的负数向负方向偏移一个数,不会有正0和负0之分了。
变形补码
为便于判断运算结果是否溢出,还采用一种双符号位的补码表示,称为变形补码,也称模4补
码。
在双符号位中,左符表示真正的符号位,右符用于判断“溢出”。
假定变形补码的位数为n+1(其中符号位占2位,数值位占n-1位)。
(3)反码表示法(了解)
负数的补码可采用“按位取反,末位加1”的方法得到,
若仅“按位取反”而末位不加1,则就是负数的反码表示。
正数的反码表示和相应的原码表示相同。
(4)移码表示法
移码常用来表示浮点数的阶码,它只能表示整数。
移码就是在真值X上加上一个常数(偏置值),通常这个常数取2的n次幂,相当于X在数轴上向正
方向偏移了若干单位,这就是“移码”一词的由来。移码的定义如下。
正数的移码:
10101+1,000 0000=1,001 0101
负数的移码:
-10101+1,000 0000=0,110 1011
数值位与补码相同,符号位相反
移码的表示范围可以同补码理解
①原码、补码、反码的符号位相同,正数的机器码相同。
②原码、反码的表示在数轴上对称,二者都存在+0和-0两个0。
③补码、移码的表示在数轴上不对称,零的表示唯一,它们比原码、反码多表示一个数。
④原码很容易判断大小。而负数的补码、反码很难直接判断大小,可采用如下规则快速判
断算对于负数,数值位部分越小,其绝对值越大,即负得越多。
2.1.3 整数的表示
1.无符号整数的表示
当一个编码的全部二进制位均为数值位而没有符号位时,该编码表示就是无符号整数,
简称无符号数。此时,默认数的符号为正。因为无符号整数省略了一位符号位,所以在字长
相同的情况下,它能表示的最大数比有符号整数能表示的大。一般在全部是正数运算且不出
现负值结果的场合下,使用无符号整数表示。例如,可用无符号整数进行地址运算,或用它
来表示指针。
2.有符号整数的表示
将符号数值化,并将符号位放在有效数字的前面,就组成了有符号整数。虽然前面介绍的原
码、补码、反码和移码都可以用来表示有符号整数,但补码表示有其明显的优势:
①与原码和反码相比,0的补码表示唯一。
②与原码和移码相比,补码运算规则比较简单,且符号位可以和数值位一起参加运算。
③与原码和反码相比,补码比原码和反码多表示一个最小负数。
计算机中的有符号整数都用补码表示,所以n位有符号整数的表示范围是-2*1~2”1—1。
2.1.4 C语言中整数类型及类型转换
1.C语言中的整型数据类型
C语言中,有符号整数根据位数的不同,可分为短整型(short或short int,16位)、整型(int,
32位)、长整型(long或longint,在32位机器中为32位,在64位机器中为64位)。
要定义无符号整数,只需在short/int/long之前加上关键字unsigned,如无符号短整(unsigned short或unsigned short int)、无符号整型(unsigned int)、无符号长整型(unsigned long或unsigned long int)。
若不指定 signed/unsigned时,则默认为有符号整数。
字符型(char,8位)是C语言中的一个特殊类型,默认按无符号整数解释。
上述类型都是按补码形式存储的,只是有符号整数的最高位代表符号,而无符号整数的全部二进制位都表示数值,没有符号位,相当于数的绝对值,因此两者所表示的数据范围有所不同。
2.有符号数和无符号数的转换
C语言允许在不同的数据类型间做类型转换。强制类型转换的代码格式为“TYPE b=(TYPE)a”,强制类型转换后,返回一个具有TYPE类型的数值。先看由short型转换到unsigned short型的情况。考虑如下代码片段:
int main(){
short x=-4321;
unsigned short y=(unsigned short)x;
printf("x=%d,y=%u\n",x,y);
}
有符号整数是一个负数,而无符号整数y只能表示一个正数,它们在计算机内部都占16位,y的表示范围显然不包括x的值。
上述程序会输出如下结果:
X = -4321, Y= 61215
输出的结果中,得到的y值似乎与原来的x没有一点关系。不过将这两个数转换为二进制表示时,我们就会发现其中的规律,如表2.1所示。
观察可知,将位数相同的short型强制转换为unsigned short型,两个变量对应的每位都是相同的,即强制类型转换的结果是保持二进制各位的位值不变,仅改变解释这些位的方式。
再看由unsigned short型转换到short型的情况。考虑如下代码片段:
int main() {
unsigned short x=65535;
short y=(short)x;
printf("x=%u, y=%d\n", X, Y);
}
上述程序会输出如下结果:
X = 65535, Y = -1
把这两个数转换为二进制表示,变量x对应的二进制表示为16位全1,若按有符号数的规则解释,则16位全1对应的真值是-1,同样可证实之前的结论。
因此,位数相同的有符号数转换为无符号数时,符号位解释为数值的一部分,负数转换为无符号数时数值将发生变化。同理,位数相同的无符号数转换为有符号数时,最高位解释为符号位,也可能发生数值的变化。
注意:若同时有无符号数和有符号数参与运算,则C语言标准规定按无符号数进行运算。
3.不同字长整数之间的转换
另一种常见的运算是在不同字长的整数之间进行类型转换。
先看大字长变量向小字长变量转换的情况。考虑如下代码片段:
int main() {int x=165537,u=-34991; //int 型占用4Bshort y=(short)x, v=(short)u; //short型占用2Bprintf("x=%d, y=%d\n", x, y);printf("u=%d, v=%d\n", u, v);
}
运行结果如下:
x=165537, y=-31071
u=34991, v=30545
其中x,y,u,v的十六进制表示分别为0x000286a1,0x86a1,0xffff7751,0x7751,观察上述数字容易得出结论,当大字长向小字长转换时,系统把多余的高位部分直接截断,低位部分直接赋值。
再看小字长变量向大字长变量转换的情况。考虑如下代码片段:
int main(){short x =-4321;int y=x;unsigned short u= (unsigned short)x;unsigned int v=u;printf("x=%d, y=%d\n", x, y);printf("u=%u, v=%u\n", u, v);
}
运行结果如下:
x=-4321,y=-4321
u = 61215,v = 61215
命题追踪
零扩展和符号扩展的应用(2012、2021、2024)
x,y,u,v的十六进制表示分别为0xef1f,0xffffef1f,0xef1f,0x0000ef1f。由本例可知,从小字长转换为大字长时,要对高位部分进行扩展。
若原数字是无符号整数,则进行零扩展,扩展后的高位部分用0填充(例如,当16位无符号整数u强制转换为32位无符号整数v时,高16位用0填充)。
若原数字是有符号整数,则进行符号扩展,扩展后的高位部分用原数字符号位填充(例如,当16位有符号整数x强制转换为32位有符号整数y时,因为x的符号位是1,所以高16位用1填充)。
注意,char型为8位无符号整数,其在转换为int型时高位补0即可。
在有符号数和无符号数的转换中,若两个变量的字长不同,则分两种情况进行讨论:
①若从小字长转换到大字长,则要先对原数字的高位部分进行扩展,若原数字是无符号整数,则进
行零扩展;若原数字是有符号整数,则进行符号扩展。
②若从大字长转换到小字长,则直接截取低位部分。也就是说,先进行字长的转换,再进行符号的转换。
2.2 运算方法和运算电路
2.2.1 基本运算部件
在计算机中,运算器由算术逻辑单元(Arithmetic Logic Unit,ALU)、移位器、状态寄存器
(PSW)和通用寄存器组等组成。
运算器的基本功能包括加、减、乘、除四则运算,
与、或、非、异或等逻辑运算,
以及移位、求补等操作。
ALU的核心部件是加法器。
1.一位全加器
全加器(FA)是最基本的加法单元,有加数Ai、加数Bi与低位传来的进位共三个输入,
有本位和Si及向高位的进位Ci共两个输出。
全加器的逻辑表达式如下。
一位全加器对应的逻辑结构如图2.3(a)所示,其逻辑符号如图2.3(b)所示。
2.串行进位加法器
将n个全加器相连可得到n位加法器,称为串行进位加法器,如图2.4所示。串行进位也称行波进位,每级进位直接依赖于前一级的进位,即进位信号是逐级形成的。
图2.4中的加法器实现了两个n位二进制数A=AnAn-1…A1和B=BnBn-1…B1逐位相加的功能,得到的二进制和为S=SnSn-1...S1,进位输出为Cn。
例如,当A=11...11,B=00...01时,结果输出为S=00···00且Cn=1。因为位数有限,高位自动丢失,所以实际是模2的n次幂的加法运算。
在串行进位加法器中,低位运算产生进位所需的时间将影响高位运算的时间。因此,串行进位加法器的最长运算时间主要是由进位信号的传递时间决定的,位数越多,延迟时间就越长,所
以加快进位产生和提高传递的速度是关键。
3.并行进位加法器*
并行进位(也称先行进位)加法器可以加快进位产生的速度,进而提升加法运算产生结果的速度。
构造一个n位并行进位加法器,需要将n个一位全加器连接上n位先行进位部分(简称CLA部件),其作用是“并行产生进位”,即n位进位信息几乎是同时产生的。
因此,相比于串行进位加法器,并行进位加法器提升了加法运算产生结果的速度。图2.5所示是一个4位全先行进位加法器。随着加法器位数的增加,电路结构会变得更复杂,这里不再深入讨论。
4.带标志加法器
对于n位加法器,除了需要得到运算结果,还要关注加法运算是否发生溢出、运算结果的正负性、运算结果是否为0等,这些信息对于程序的执行控制至关重要。
因此,需要在n位加法器的基础上增加一些逻辑电路,使其不仅能计算和/差,还能生成相应的标志信息:分别是OF、CF、SF和ZF,每个标志信息占1位。
图2.6是用全加器实现n位带标志加法器的电路。在图2.6中,
溢出标志OF=⊕
,用于判断有符号数的加减运算是否溢出,OF=0表示未溢出,OF=1表示溢出。
符号标志SF=,用于表示有符号数的加减运算结果的正负性,SF=0表示结果为正,SF=1表示结果为负。
零标志ZF=1当且仅当F=0,表示加减运算的结果是否为0,ZF=1表示结果为0,ZF=0表示结果非0。
进位/借位标志CF=Cout⊕Cin,用于判断无符号数的加减运算是否发生溢出,ZCF=0表示未溢出,CF=1表示溢出。
5.算术逻辑单元(ALU)
ALU是一种功能较强的组合逻辑电路,它能进行多种算术运算和逻辑运算。加、减、乘、除运算最终都能归结为加法运算,因此ALU的核心是带标志加法器,同时也能执行“与”“或”“非”等逻辑运算。
ALU的基本结构如图2.7所示,其中A和B是两个n位操作数输入端,Cin是进位输入端,ALUop是操作控制端(发出控制信号),用来决定ALU所执行的处理功能。
例如,ALUop选择Add运算,ALU就执行加法运算,输出的结果就是A加B之和。ALUop的位数决定了操作的种类。例如,当位数为3时,ALU最多只有8种操作。
图2.8给出了能够完成3种运算“与”“或”和“加法”的一位ALU结构图。
其中,一位加法用一个全加器实现,在ALUop的控制下,由一个多路选择器(MUX)选择输出3种操作结果之一。
这里有3种操作,所以ALUop至少要有两位。
同时,ALU也可以实现左移或右移的移位操作。
2.2.2 定点数的移位运算
当计算机中没有乘/除法运算电路时,可以通过加法和移位相结合的方法来实现乘/除法运算。
对于任意二进制整数,左移一位,若不产生溢出,相当于乘以2(与十进制数的左移一位相当于乘以10类似);右移一位,若不考虑因移出而舍去的末位尾数,相当于除以2。
根据操作数的类型不同,移位运算可以分为逻辑移位和算术移位。
1.逻辑移位
逻辑移位将操作数视为无符号整数。
逻辑移位的规则:
左移时,高位移出,低位补0;
右移时,低位移出,高位补0。
对于无符号整数的逻辑左移,若高位的1移出,则发生溢出。
2.算术移位
算术移位需要考虑符号位的问题,即将操作数视为有符号整数。
计算机中的有符号整数都是用补码表示的,因此对于有符号整数的移位操作应采用补码算术移位方式。
算术移位的规则:
左移时,高位移出,低位补0,若移出的高位不同于移位后的符号位,即左移前后的符号位不同,则发生溢出;
右移时,低位移出,高位补符号位,若低位的1移出,则影响精度。
例如,补码1001和0101左移时会发生溢出,右移时会丢失精度。
2.2.3 定点数的加减运算
1.补码的加减运算
补码加减运算规则简单,易于实现。补码加减运算的公式如下(设机器字长为n+1)。
[A+ B]补=[A]补 +[B]补(mod 2”+1)
[A-B]补=[A]补 +[-B]补(mod 2"+1)
补码运算的特点如下。
1)按二进制运算规则运算,逢二进一。
2)若做加法,两个数的补码直接相加;若做减法,则将被减数与减数的负数补码相加。
3)符号位与数值位一起参与运算,加、减运算结果的符号位也在运算中直接得出。
4)最终运算结果的高位丢弃,保留n+1位,运算结果亦为补码。
2.溢出判别方法
仅当两个符号相同的数相加或两个符号相异的数相减才可能产生溢出,
如两个正数相加,而结果的符号位却为1(结果为负);
一个负数减去一个正数,结果的符号位却为0(结果为正)。
补码定点数加减运算溢出判断的方法有3种。
(1)采用一位符号位
减法运算在机器中是用加法器实现的,因此无论是加法还是减法,只要参加操作的两个数的符号相同,结果又与原操作数的符号不同,则表示结果溢出。
设A的符号为As,B的符号为Bs,运算结果的符号为Ss,则溢出逻辑表达式为
若V=0,表示无溢出;
若V=1,表示有溢出。
(2)采用双符号位
双符号位法也称模4补码。运算结果的两个符号位相同,表示未溢出;
运算结果的两个符号位不同,表示溢出,此时最高位符号位代表真正的符号。
符号位的各种情况如下:
①=00:表示结果为正数,无溢出。
②=01:表示结果正溢出。
=10:表示结果负溢出。
④=11:表示结果为负数,无溢出。
溢出逻辑判断表达式为,若V=0,表示无溢出;若V=1,表示有溢出。
(3)采用一位符号位根据数值位的进位情况判断溢出
若符号位(最高位)的进位Cn,与最高数位(次高位)的进位Cn-1相同,说明无溢出,否则说明有溢出。
溢出逻辑判断表达式为,若 V=0,表示无溢出;V=1,表示有溢出。
3.加减运算电路
已知一个数的补码表示为Y,则这个数的负数的补码为Y非+1,
因此,只要在原加法器的Y输入端加n个反向器以实现各位取反的功能,然后加一个2选1多路选择器,用一个控制端Sub来控制,
以选择是将Y输入加法器还是将Y非输入加法器,
并将Sub同时作为低位进位送到加法器(做减法时实现末位加1),如图2.9所示。
该电路可实现模2的n次幂补码加减运算。
当Sub为1时,做减法,实现;
当Sub为0时,做加法,实现
无符号整数相当于正整数的补码表示,
因此图2.9的电路同时也能实现无符号数的加/减运算,
对于有符号数х和y,图中的X和Y分别是x和у的补码表示;
对于无符号数x和y,图中的X和Y分别是x和y的二进制表示。
不论是补码减法还是无符号数减法,都是用被减数加上减数的负数的补码(Y非+1)来实现的。
注意
运算器本身无法识别所处理的二进制串是有符号数还是无符号数。
例如,0-1=00..0+11...1=11..1,
若解释为有符号数,对应值为-1,结果正确;
若解释为无符号数,对应值为2的n次幂-1(n位无符号数的最大值),结果出错。
此类易混点是统考极易考查的内容。
可通过标志信息来区分有符号整数运算结果和无符号整数运算结果。
标志信息
零标志ZF:ZF=1表示结果F为0。对于无符号数和有符号数的运算,ZF都有意义。
溢出标志OF:判断有符号数运算是否溢出,它是符号位进位与最高数位进位的异或结果,
即。
对于无符号数运算,OF没有意义,通俗地说,就是根据OF无法判断无符号数运算是否溢出。例如,无符号数加法010+011=101,此时0F=1,但结果未溢出。
符号标志SF:表示结果的符号,即F的最高位。对于无符号数运算,SF没有意义。
进/借位标志CF:表示无符号数运算时的进位/借位,判断是否发生溢出。
加法时,CF=1表示结果溢出,因此CF等于进位输出Cout。
减法时,CF=1表示有借位,即不够减,所以CF等于进位输出Cout取反。
综合可得CF=Sub⊕out。
例如,无符号数加法10+011最高位产生进位,无符号数减法000-111最高位产生借位,结果均发生溢出(CF=1)。
对于有符号数运算,CF没有意义,也就是说,根据CF无法判断有符号数运算是否溢出。
(1)无符号数大小的比较
对于无符号数的运算,零标志ZF、进/借位标志CF才有意义。
假设有两个无符号数A和B,下面以执行A-B为例来说明ZF、CF标志的几种可能情况。
若A=B,如A-B=011-011=000,此时结果为零ZF=1,无借位CF=0。
若A>B,如A-B=010-001=001,此时结果非零ZF=0,无借位CF=0。
若A<B,如A-B=000-001=(1)000-001=111,此时ZF=0,有借位CF=1。
总结:
当ZF=1时,说明A=B。
当ZF=0且CF=0时,说明A>B。
当CF=1时,说明A<B。
(2)有符号数大小的比较
对于有符号数的运算,零标志ZF、溢出标志OF、符号标志SF才有意义。
假设两个有符号数A和B,用补码表示,以执行[A]补-[B]补为例来说明ZF、OF、SF标志的几种可能情况。
若A=B,如[A]补-[B]补=011-011=[A]补+[-B]补=011+101=(1)000,
此时结果为零,即ZF=1,X最高位进位与次高位进位的异或结果OF=C3⊕C2=0,结果的最高位SF=0。
若A>B,如[A]补-[B]补=010-001=010 + 111=(1)001,此时 ZF=0,OF=0,SF=0;
又如[A]补-[B]补=011-101=011+011=110,此时ZF=0,OF=1,SF=1。
若A<B,如[A]补-[B]补=000-001=000+ 111=111,此时ZF=0,OF=0,SF=1。
又如[A]补-[B]补=101-011=101+101=(1)010,此时ZF=0,OF=1,SF=0。
总结:
当ZF=1时,说明A=B。
当ZF=0且未发生溢出时,即OF=0时,若SF=0,则表示结果非负,说明A>B;
当发生溢出时,即OF=1时,若SF=1,则必然是正数减去负数发生溢出导致结果为负,因此,当OF=SF(或OF⊕SF=0)且ZF=0时,说明A>B。
当ZF=0且未发生溢出时,即OF=0时,若SF=1,则表示结果为负,说明A<B;
当发生溢出时,即OF=1时,若SF=0,则必然是负数减去正数发生溢出导致结果为正,因此,当OF+SF(或OF⊕SF=1)且ZF=O时,说明A<B。
4.原码的加减运算(了解)
在原码加减运算中,将符号位和数值位分开处理,具体的规则如下。
加法规则:遵循“同号求和,异号求差”的原则,先判断两个操作数的符号位。
具体来说,符号位相同,则数值位相加,结果符号位不变,若最高数值位相加产生进位,则发生溢出;
符号位不同,则做减法,绝对值大的数减去绝对值小的数,结果符号位与绝对值大的数相同。
减法规则:先将减数的符号取反,然后将被减数与符号取反后的减数按原码加法进行运算。
注意
原码的加减运算规则比较复杂,因此计算机采用的大多是补码加/减运算。
2.2.4 定点数的乘除运算
1.定点乘法运算
(1)乘法运算的基本原理
原码乘法的特点是符号位与数值位是分开求的,
原码乘法运算分为两步:
①乘积的符号位由两个乘数的符号位“异或”得到;
②乘积的数值位是两个乘数的绝对值之积。
两个定点数的数值部分之积可视为两个无符号数的乘积。
下面是两个无符号数相乘的手算过程。
上述过程可写成数学推导过程:
更普遍地,n位无符号数乘法X×Y可递归地定义如下。
其中,为运算的中间值。
按上例,=110.1
=11.01+110.1
=1.101+11.01+000.0
=0.1101+1.101+00.00+110.1
将小数点对齐,相当于上述(两个无符号数相乘的手算过程)的中间过程的每添加一次运算结果并右移一位
由上述分析可知,乘法运算可用加法和移位运算来实现(乘以相当于做一次右移),两个n位无符号数相乘共需进行n次加法和n次移位运算。
原码乘法运算的过程可归纳如下:
①被乘数和乘数均取绝对值参加运算,视为无符号数,符号位为⊕
。
②部分积是乘法运算的中间结果,初值
=0。
从乘数的最低位开始,将前面所得的部分积
加上X×
,然后右移一位,此步骤重复n次。
注意
参与运算的是两个数的数值位,因此运算过程中的右移操作均为逻辑右移。
(2)乘法运算电路
图2.10是32位无符号数乘法运算的逻辑结构图。
部分积和被乘数X做无符号数加法时,可能产生进位,因此设置一个专门的进位位C。
乘积寄存器P初始置0。
计数器初值为32,每循环一次减1。
ALU是乘法器的核心部件,对乘积寄存器P和被乘数寄存器X的内容做“无符号加法”运算,结果送回乘积寄存器P,进位存放在C中。
每次循环都对进位位C、寄存器P和寄存器Y实现同步“逻辑右移”,此时,进位位C移入寄存器P的最高位,寄存器Y的最低位移出。
每次从寄存器Y移出的最低位都被送到控制逻辑,以决定被乘数是否“加”到部分积上。
无符号数和有符号数乘法指令的溢出判断(2019、2020、2021)
在字长为32位的计算机中,对于两个int型变量x和y的乘积,若乘积高32位的每一位都相同,且都等于乘积低32位的符号,则表示不溢出,否则表示溢出。
当x和y都为unsigned int型变量时,若乘积的高32位全为0,则表示不溢出,否则表示溢出。
注意
统考真题还涉及过阵列乘法器的基本概念。阵列乘法器是一种快速乘法器,它采用硬件叠加的方式,所有部分积同时产生并组成一个阵列,再运用多操作数相加,就能得到最终的积,因此最快可在一个时钟周期内完成一条乘运算指令。