上篇:第五章、输入输出系统
下篇:第七章、指令系统
信息在机器内部的形式都是一致的,均以 0
和 1
组成的各种编码,以下内容主要介绍参与运算的各种数据(无符号数和有符号数,定点数和浮点数等)以及它们在计算机中的算术运算方法。
在计算机中参与运算的数有两大类,分别是:无符号数和有符号数。
所谓无符号数即没有符号的数,在寄存器中的每一位均可用来存放数值。以机器字长为 n 为例,无符号数的表示范围为 0 ~ 2n-1。
1. 机器数与真值
对于有符号数而言,符号的 “正”、“负” 机器是无法识别的,但由于 “正”、“负” 恰好是两种截然不同的状态,正好可以用 “0” 表示 “正”,用 “1” 表示 “负”,这样符号也被数字化了,并且规定将它放在有效数字的前面,这样就组成了有符号数。当存放有符号数时,则需留出位置存放 “符号”,同样以机器字长为 n 为例,有符号数的表示范围为 -2n-1-1 ~ 2n-1-1。
把符号 ”数字化“ 的数叫作机器数
,而把带 “+” 或 ”-“ 符号的数叫作真值
。
以二进制数 +0.1011
、-0.1011
、+1011
、-1011
为例,其机器数表示:
小数点是以约定的方式给出,没有任何硬件用于标识小数点的位置,这样可以将定点计算机分为两类,一类是小数点在符号位的后面,这种机器称为小数定点器;另外一类就是小数点在数值的后面,就是整数定点器。
2. 原码表示法
计算机中所有的数均用 0
和 1
编码表示,数字的正负号也不例外,如果一个机器数字长是 n
位的话,约定最左边一位用作符号位,其余 n-1
位用于表示数值。其符号位为 0
表示正数,符号位为 1
表示负数,数值位即真值的绝对值。凡不足 n-1
位的,小数在最底位右边加零;整数则在最高位左边加零已补足 n-1
位。这种计算机的编码形式叫作原码
,又称作带符号的绝对值表示
。记作 [X]原。
原码的定义:
例如:(字长为 5 )
当 x = +0.1101 时,[X]原=0.1101
当 x = -0.1101 时,[X]原=1-(-0.1101)=1.1101
例如:(字长为 5 )
当 x = +1110 时,[X]原=0,1110
当 x = -1110 时,[X]原=24-(-1110)=1,1110
为了区分整数和小数,约定整数的符号位与数值位之间用逗号 ","
隔开;小数的符号位与数值之间用小数点 "."
隔开。
如上面四个数在字长为 8 的机器数下原码分别表示为:
真值 | 公式 | 原码 (8字长) |
---|---|---|
+0.1011 | [+0.1011]原 = 0.1011 | 0.1011000 |
-0.1011 | [-0.1011]原 = 1.1011 | 1.1011000 |
+1100 | [+1100]原 = 0,1100 | 0,0001100 |
-1100 | [-1100]原 = 1,1100 | 1,0001100 |
0
的原码可分为四种情况:
真值 | 公式 | 原码 (8字长) |
---|---|---|
+0.0000 | [+0.0000]原 = 0.0000 | 0.0000000 |
-0.0000 | [-0.0000]原 = 1.0000 | 1.0000000 |
+0 | [+0]原 = 0,1100 | 0,0000000 |
-0 | [-0]原 = 1,1100 | 1,0000000 |
由此可得:[+0]原 != [-0]原
原码的表示虽然比较简单明了,且易于和真值进行转换,但是进行加减运算时却有很多麻烦,例如:
操作命令 | A的符号 | B的符号 | 实际操作 | 结果符号 |
---|---|---|---|---|
加法 | 正 | 正 | 加法 | 正 |
加法 | 正 | 负 | 减法 | 可正可负 |
加法 | 负 | 正 | 减法 | 可正可负 |
加法 | 负 | 负 | 加法 | 负 |
一个加法运算,实际上会因为符号的差别,在实际操作的过程中变成减法运算,能否让它只作加法呢?
找到一个与负数等价的正数来代替这个负数,就可使减法转变为加法。而机器数采用补码时就能满足此要求。
3. 补码表示法
在介绍补码概念之前,先介绍一下“模”的概念:“模”是指一个计量系统的计数范围,如过去计量粮食用的斗、时钟等。计算机也可以看成一个计量机器,因为计算机的字长是定长的,即存储和处理的位数是有限的,因此它也有一个计量范围,即都存在一个“模”。如:时钟的计量范围是 0~11,模=12。表示 n 位的计算机计量范围是 0 ~ 2n-1,模 = 2n。“模” 实质上是计量器产生 “溢出” 的量,它的值在计量器上表示不出来,计量器上只能表示出模的余数。任何有模的计量器,均可化减法为加法运算。
假设当前时针指向 6 点,而准确的时间是 3 点,调整时间可有以下两种拨法:一种是倒拨 3 个小时,即 6-3;另一种是顺拨 9 小时,即 6+9=12+3=6,即 6-3=6+9=6+12-3(mod 12),在 12 为模的系统里,加 9 和减 3 的效果是一样的,因此凡是减 3 的运算都可以用加 9 来代替。若用一般公式可表示为:a-b=a-b+mod=a+mod-b。对 “模” 而言,3 和 9 互为补数。实际上,以 12 为模的系统中,11和1,10和2,8和4,7和5,6和6都有这个特性,共同的特点是两者相加等于模,也可以说当模为 12
时, 9
是 -3
的补数。
对于计算机,其概念和方法完全一样。n 位计算机,设 n=8,所能表示的最大数是 11111111,若再加 1 成 100000000(9位),但因只有8 位,最高位 1 自然丢失(相当于丢失一个模)。又回到了 00000000,所以 8 位二进制系统的模为 28。在这样的系统中减法问题也可以化成加法问题,只需把减数用相应的补数表示就可以了。把补数用到计算机对数的处理上,就是补码。记作 [X]补。
补码的定义:
例如:(字长为 5 )
当 x = +0.1001 时,[X]补=0.1001
当 x = -0.0110 时,[X]补=2+x=10.0000-0.0110=1.1010
例如:(字长为 5 )
当 x = +1010 时,[X]补=0,1010
当 x = -1101 时,[X]补=2n+1+x=100000-1101=1,0011
求补码的快捷方式:
① 当真值为 正 时,补码就是其原码的本身
② 当真值为 负 时,补码可用原码除符号位每位取反,末位加 1 求得
如上面四个数在字长为 8 的机器数下补码分别表示为:
真值 | [x]原 (8字长) | [x]补 (8字长) |
---|---|---|
+0.1011 | 0.1011000 |
0.1011000 |
-0.1011 | 1.1011000 |
1.0101000 |
+1100 | 0,0001100 |
0,0001100 |
-1100 | 1,0001100 |
1,1110100 |
0
的补码可分为四种情况:
真值 | [x]原 (8字长) | [x]补 (8字长) |
---|---|---|
+0.0000 | 0.0000000 |
0.0000000 |
-0.0000 | 1.0000000 |
0.0000000 |
+0 | 0,0000000 |
0,0000000 |
-0 | 1,0000000 |
0,0000000 |
由此可得:[+0]补 = [-0]补
4. 反码表示法
反码通常是用来由原码求补码或者由补码求原码的过渡码。
反码的定义:
例如:(字长为 5 )
当 x = +0.0110 时,[X]反=0.0110
当 x = -0.0110 时,[X]反=(2-2-4)+x=1.1111-0.0110=1.1001
例如:(字长为 5 )
当 x = +1101 时,[X]反=0,1101
当 x = -1101 时,[X]反=(24+1-1)+x=11111-1101=1,0010
如上面四个数在字长为 8 的机器数下反码分别表示为:
真值 | [x]原 (8字长) | [x]补 (8字长) | [x]反 (8字长) |
---|---|---|---|
+0.1011 | 0.1011000 |
0.1011000 |
0.1011000 |
-0.1011 | 1.1011000 |
1.0101000 |
1.0100111 |
+1100 | 0,0001100 |
0,0001100 |
0,0001100 |
-1100 | 1,0001100 |
1,1110100 |
1,1110011 |
0
的反码可分为四种情况:
真值 | [x]原 (8字长) | [x]补 (8字长) | [x]反 (8字长) |
---|---|---|---|
+0.0000 | 0.0000000 |
0.0000000 |
0.0000000 |
-0.0000 | 1.0000000 |
0.0000000 |
1.1111111 |
+0 | 0,0000000 |
0,0000000 |
0,0000000 |
-0 | 1,0000000 |
0,0000000 |
1,1111111 |
由此可得:[+0]反 != [-0]反
综上所述,三种机器数的特点可归纳如下:
"."
(对于小数)或 ","
(对于整数)隔开0
表示,数值部分与真值相同1
表示,而数值部分有如下关系,即补码是原码的 求反加 1
,反码是原码的 每位求反
假设机器数字长位 8 位(其中一位为符号位),对于整数,当其分别代表无符号数、原码、补码和反码时,对应的真值范围:
5. 移码表示法
当真值用补码表示时,由于符号位和数值部分一起编码,与习惯上的表示不同,因此人们很难从补码的形式上直接判断其真值的大小。
例如:(假设机器字长为 6 位)
十进制的数 x = 21 ,对应的二进制数为 + 10101 ,则 [ x ] 补 = 0 , 10101 十进制的数 x = − 21 ,对应的二进制数为 − 10101 ,则 [ x ] 补 = 1 , 01011 十进制的数 x=21,对应的二进制数为 +10101,则[x]_{补}=0,10101 \newline 十进制的数 x=-21,对应的二进制数为 -10101,则[x]_{补}=1,01011 十进制的数x=21,对应的二进制数为+10101,则[x]补=0,10101十进制的数x=−21,对应的二进制数为−10101,则[x]补=1,01011
上述补码表示中 ","
逗号在计算机内部是不存在的,因此,从代码形式看,符号位也是一位二进制数。按这六位二进制代码比较其大小的话就会得出 101011 > 010101,其实恰恰相反
如果对每个真值加上一个 2n ( n 为整数的位数),情况就会发生了变化,如:
x = 10101 加上 2 5 可得 10101 + 100000 = 110101 x = − 10101 加上 2 5 可得 − 10101 + 100000 = 001011 x=10101 加上 2^{5} 可得 10101+100000=110101 \newline x=-10101 加上 2^{5} 可得 -10101+100000=001011 x=10101加上25可得10101+100000=110101x=−10101加上25可得−10101+100000=001011
比较它们的结果可见,110101 > 001011,这样一来从六位代码本身就可看出真值的实际大小。
由此可得移码的定义:
[ x ] 移 = 2 n + x ( 2 n > x ≥ − 2 n ) [x]_{移}=2^{n}+x \quad\quad (2^{n}>x\ge -2^{n}) [x]移=2n+x(2n>x≥−2n)
其中 X 表示真值,[X]移:机器数的移码表示形式,n 为真值的位数
例如:(字长为 6 )
当 x = 10100 时,[X]移=25+10100=1,10100
当 x = -10100 时,[X]移=25-10100=0,01100
如上面四个数在字长为 8 的机器数下移码分别表示为:
真值 | [x]原 (8字长) | [x]补 (8字长) | [x]反 (8字长) | [x]移 (8字长) |
---|---|---|---|---|
+0.1011 | 0.1011000 |
0.1011000 |
0.1011000 |
1.1011000 |
-0.1011 | 1.1011000 |
1.0101000 |
1.0100111 |
0.0101000 |
+1100 | 0,0001100 |
0,0001100 |
0,0001100 |
1,0001100 |
-1100 | 1,0001100 |
1,1110100 |
1,1110011 |
0,1110100 |
0
的移码可分为四种情况:
真值 | [x]原 (8字长) | [x]补 (8字长) | [x]反 (8字长) | [x]移 (8字长) |
---|---|---|---|---|
+0.0000 | 0.0000000 |
0.0000000 |
0.0000000 |
1.0000000 |
-0.0000 | 1.0000000 |
0.0000000 |
1.1111111 |
1.0000000 |
+0 | 0,0000000 |
0,0000000 |
0,0000000 |
1,0000000 |
-0 | 1,0000000 |
0,0000000 |
1,1111111 |
1,0000000 |
由此可得:[+0]补 = [-0]补
进一步观察发现,同一个真值的移码和补码仅差一个符号位,简单的说就是:原码的补码在符号位上取反就是移码。
在计算机中,小数点不用专门的器件表示,而是按约定的方式标出,共有两种方法来表示小数点的存在,即定点表示
和浮点表示
。定点表示的数称为定点数
,浮点表示的数称为浮点数
。
小数点固定在某一位置的数为定点数,有以下两种格式:
当小数点位于符号位和第一数值位之间时,机器内的数为纯小数;当小数位于数值位之后,机器内的数为纯整数。
采用定点数的机器叫做定点机
。数值部分的位数 n
决定了定点机中数的表示范围。
定点机 | 小数定点机 | 整数定点机 |
---|---|---|
原码 | -(1-2-n) ~ +(1-2-n) | -(2n-1) ~ +(2n-1) |
补码 | -1 ~ +(1-2-n) | -2n ~ +(2n-1) |
反码 | -(1-2-n) ~ +(1-2-n) | -(2n-1) ~ +(2n-1) |
在定点机中,由于定点机中的小数点位置固定不变,所以机器处理的数不是纯小数或纯整数时,必须乘上一个比例因子,否则会产生溢出。
实际上计算机中处理的数不一定是纯小数或纯整数,而且有些数据的数值范围相差很大,它们都不能直接用定点小数或定点整数表示,但均可用浮点数表示。
浮点数
即小数点的位置可以浮动的数,如:
352.47 = 3.5247 × 1 0 2 = 3524.7 × 1 0 − 1 = 0.35247 × 1 0 3 352.47=3.5247×10^{2}\\ \quad\quad\quad\;\; = 3524.7×10^{-1}\\ \quad\quad\quad\;\; = 0.35247×10^{3} 352.47=3.5247×102=3524.7×10−1=0.35247×103
显然,这里小数点的位置是变化的,但因为分别乘上了不同的 10 的幂次方,故值不变。
通常浮点数可以表示成:
N = S × r j N=S×r^{j} N=S×rj
式中 S 为尾数(可正可负),j 为阶码(可正可负),r 是基数(或基值)
计算机中基数 r
可取 2
、4
、8
或 16
等,以基数 2
为例,数 N 可写成下列不同形式:
N = 11.0101 = 0.110101 × 2 10 = 1.10101 × 2 1 = 1101.01 × 2 1 = 0.00110101 × 2 100 = . . . . . . N=11.0101\\ \quad\quad\quad\quad\; = 0.110101×2^{10}\\ \quad\quad\quad\;\; = 1.10101×2^{1}\\ \quad\quad\quad\;\; = 1101.01×2^{1}\\ \quad\quad\quad\quad\quad\;\;\ = 0.00110101×2^{100}\\ =...... N=11.0101=0.110101×210=1.10101×21=1101.01×21 =0.00110101×2100=......
PS:二进制中 2x 中的 x 也是二进制表示,比如 x=10,就是 2,则是向右移动 2 位;x=-110,就是 -3,则向左移动 3 位
在计算机中规定浮点数的尾数用纯小数形式,故上例中 0.110101×210
和 0.00110101×2100
是可以采用的。此外,将尾数最高位为 1
的浮点数称作规格化数
,即 0.110101×210
为浮点数的规格化形式。
1. 浮点数的表示形式
浮点数在机器中的形式如下:
组成部分:
j
— 阶码部分
jf
— 阶符:代表阶码的正负 j1j2 ··· jm
— 阶码的数值部分:结合阶符反应浮点数的表示范围及小数点的实际位置S
— 尾数部分
Sf
— 数符:代表浮点数的正负 S1S2 ··· Sn
— 尾数的数值部分:尾数是小数,其位数 n
反应了浮点数的精度采用这种数据格式的机器叫作浮点机
。
2. 浮点数的表示范围
以通式 N=S×rj
为例,设浮点数阶码的数值取 m
位,尾数的数值位取 n
位,当浮点数为非规格化数时
当浮点数阶码大于最大阶码时,称为 “上溢”,此时机器停止运算,进行中断溢出处理;当浮点数阶码小于最小阶码时,称为 “下溢”,此时 “溢出” 的绝对值很小,通常将尾数各位强制为零,按机器零处理,此时机器可以继续运行。
3. 浮点数的规格化
为了提高浮点数的精度,其尾数必须规格化。如果不是规格化数,就要通过修改阶码并同时左右移尾数的办法,使其变成规格化数。将非规格化数转换成规格化数的过程叫作规格化
。规格化时,尾数左移叫做向左规格化,简称左规
;尾数右移做向右规格化,简称右规
。
对于基数不同的浮点数,因其规格化数的形式不同,规格化过程也不同。
当基数为 2(即:21)
时,尾数最高 1
位不为 0
的数为规格化数。规格化时,尾数左移 1
位,阶码减 1;尾数右移 1
位,阶码加 1。
当基数为 4(即:22)
时,尾数最高 2
位不为 0
的数为规格化数。规格化时,尾数左移 2
位,阶码减 1;尾数右移 2
位,阶码加 1。
当基数为 8(即:23)
时,尾数最高 3
位不为 0
的数为规格化数。规格化时,尾数左移 3
位,阶码减 1;尾数右移 3
位,阶码加 1。
由此可得,当基数为 2n
时,尾数最高 n
位不为 0
的数为规格化数。规格化时,尾数左移 n
位,阶码减 1;尾数右移 n
位,阶码加 1。
浮点机中一旦基数确定后就不再变了,而且基数是隐含的,一般来说,基数 r
越大,可表示的浮点数范围越宽,但浮点数的精度反而会下降。
总之,浮点数在数的表示范围、数的精度、溢出处理和程序编码方面均优于定点数,但在运算规格、运算速度及硬件成本方面不如定点数。
现代计算机中,浮点数一般采用 IEEE
制定的国际标准,这种标准形式如下:
按 IEEE
标准,常用的浮点数有三种:
类型 | 符号位 S | 阶码 | 尾数 | 总位数 | 偏移量(十进制) | 偏移量(十六进制) |
---|---|---|---|---|---|---|
短实数 | 1 | 8 | 23 | 32 | +127 | 7FH |
长实数 | 1 | 11 | 52 | 64 | +1023 | 3FFH |
临时实数 | 1 | 15 | 64 | 80 | +16383 | 3FFFH |
其中 S
为数符,它表示浮点数的正负,但与其有效位(尾数)是分开的,阶码用移码表示,阶码的真值都被加上一个常数(偏移量)。尾数部分通常是规格化表示,即非 0
的有效位最高位总数 1
,所以在实际表示中,对短实数和长实数,这个整数位的 1
省略,称隐藏位;对于临时实数不采用隐藏位方案。
以 32
位浮点数格式为例:
S
:为数符,表示浮点数的正负,0
正 1
负阶码
:8 位以 2 为底,阶码 = 阶码真值 + 127尾数
:23 位,采用隐含尾数最高位为 1 的表示方法,实际尾数 24 位,尾数真值 = 1 + 尾数这种格式的非 0 浮点数真值为:(-1)s×2阶码-127×(1+尾数)
例 1:将 (-0.11)2 用 IEEE 短实数浮点格式表示
解:转为规格化数(隐含尾数最高位为 1)的形式:(-0.11)2= -1.1×2-1,可知阶码为:-1,尾数为:0.1
因为该数为负数,所以数符为 1:S = 1
阶码:阶码 = 阶码真值 + (127)10= (-1)2+ (127)10= (-1)2+(01111111)2=(01111110)2
尾数:0.1 => 1000 0000 0000 0000 0000 000
所以短实数浮点格式表示为 1 01111110 10000000000000000000000
例 2:将十进制数 178.125 用 IEEE 浮点格式表示
解:转为二进制数 (178.125)10=(10110010.001)2
转为规格化数(隐含尾数最高位为 1)表示:1.0110010001×2111,可知阶码为:111,尾数是:0.0110010001
因为该数为正数,所以数符为 0:S = 0
阶码:阶码 = 阶码真值 + (127)10= (111)2+ (127)10= (111)2+(01111111)2=(10000110)2
尾数:0.0110010001 => 0110 0100 0100 0000 0000 000
所以短实数浮点格式表示为 0 10000110 01100100010000000000000
例 3:将十进制数 100.25 用 IEEE 浮点格式表示
转为二进制数 (100.25)10=(1100100.01)2
转为规格化数:1.10010001×2110,可知阶码为:110,尾数是:0.10010001
因为该数为正数,所以数符为 0:S = 0
阶码:阶码 = 阶码真值 + (127)10= (110)2+ (127)10= (111)2+(01111111)2=(10000101)2
尾数:0.0110010001 => 1001 0001 0000 0000 0000 000
所以短实数浮点格式表示为 1 10000101 10010001000000000000000
定点运算包括位移、加、减、乘除几种。
1. 移位的意义
在计算机中小数点的位置是事先约定的,因此,二进制表示的机器数在相对于小数点作 n 位左移或右移时,其实质就使该数乘以或除以 2n。
移位运算又称为移位操作,对计算机来说是有很大价值的。例如,当某计算机没有乘(除)法运算线路时,可以采用移位和加法相结合实现乘(除)运算。
2. 逻辑移位规则
无符号的移位称为逻辑移位,逻辑移位的规则是:逻辑左移时,高位移出,低位添 0;逻辑右移时,低位移出,高位添 0。
3. 算术移位规则
有符号的移位称为算术移位,移位时符号位保持不变,数值部分进行位移。
对于正数,由于 [x]原 = [x]补 = [x]反 = 真值,故移位后出现的空位均以 0 添之;对于负数,由于原码、补码和反码的表示形式不同,故当机器数移位时,对于其空位的添补规则也不同。
4. 算术位移和逻辑位移的区别
例如,当寄存器内容为 01010011 时,逻辑左移为 10100110,算术左移为 00100110(最高数位 1
移丢)。又如寄存器内容为 10110010,逻辑右移为 01011001,若将其视为补码,算术右移为 11011001。
显然两种位移的结果是不同的,为了避免算术左移时最高数位丢 1
,可采用带进位(Cy
)的位移,算术左移时,符号位移至 Cy
,最高数位就可避免移出。
加法运算是计算机中最基本的运算,而减法运算也能看作是加法运算,例如:A - B = A + (-B)
之前有提过原码做加减法运算会有很多麻烦,于是采用了补码解决这类问题,所以在计算机中加减法是通过补码加减进行运算的
1. 补码加减运算的基本公式
补码加法的基本公式:
案例:设机器字长为 5 位(包含符号位)已知 A = -1001,B = -0101,求:[A + B]补
解:因为 A = -1001,B = -0101
所以 [A]补 = 1,0111,[B]补 = 1,1011
则 [A]补 + [B]补 = 11,0010
再模以 24+1 ,左边的 1 丢去得 1,0010
案例:设机器字长为 5 位(包含符号位)已知 A = 0.1011,B = -0.0101,求:[A + B]补
解:因为 A = 0.1011,B = -0.0101
所以 [A]补 = 0.1011,[B]补 = 1.1011
则 [A]补 + [B]补 = 10.0110
再模以 2 ,左边的 1 丢去得 0.0110
补码减法的基本公式:
案例:设机器字长为 8 位(包含符号位),若 A = +15,B = +24,求:[A - B]补 并还原成真值
解:因为 A =(+15)10=(0,0001111)2,B = (+24)10 = (0,0011000)2
所以 [A]补 = 0,0001111,[B]补 = 0,0011000,[-B]补 = 1,1101000
则 [A - B]补 = [A]补 + [-B]补 = 0,0001111 + 1,1101000 = 1,1110111
故 A - B = -0001001 = -9
案例:设机器字长为 8 位(包含符号位),若 A = +0.25,B = -0.125,求:[A - B]补 并还原成真值
解:因为 A =(+0.25)10=(0.0100000)2,B = (-0.125)10 = (1.0001000)2
所以 [A]补 = 0.1100000,[B]补 = 1.1111000,[-B]补 = 0.0001000
则 [A - B]补 = [A]补 + [-B]补 = 0.1100000 + 0.0001000 = 0.1101000
故 A - B = 0.0010000 = +0.25
2. 溢出判断
如上述案例中 [A-B]补 = 0,1110110,还原真值得 A - B = 118,而实际上 A - B 应该等于 -138,原因是 -138 超出了机器字长所能表示的范围。在计算机中,这种超出机器字长的现象,叫 溢出
。
补码定点加减运算判断溢出有两种方法:
(1)用一位符号位判溢出
不论是作加法还是减法,只要实际参加操作的两个数(减法时即为被减数和 “求补” 以后的减少)符号相同,结果又与原操作数的符号不同,即为溢出。
(2)用两位符号位判溢出
双符号补码又叫作 变形补码
,它是以 4
为模的,在阶码运算和溢出判断中,有着特殊的作用,定义为:
[ X ] 补 ′ = { x 1 > x ≥ 0 4 + x 0 > x ≥ − 1 ( m o d 4 ) [X]_{补'}=\left\{\begin{matrix} x \quad\quad\; 1> x\ge 0 \quad\quad\quad\quad \\ 4+x \quad\;\; 0> x\ge -1 \quad (mod\;4) \end{matrix}\right. [X]补′={x1>x≥04+x0>x≥−1(mod4)
在用变形补码作加法时,两位符号要连同数值部分一起参加运算,而且高位符号产生的进位自动丢失,便可得正确结果,即:
[ x ] 补 ′ + [ y ] 补 ′ = [ x + y ] 补 ′ ( m o d e 4 ) [x]_{补'} + [y]_{补'} = [x+y]_{补'} \quad (mode \;4) [x]补′+[y]补′=[x+y]补′(mode4)
变形补码判断溢出得原则是:当两位符号位不同时,表示溢出,否则无溢出。
不论是否发生溢出,高位(第一位)符号位永远代表真正的符号。
3. 补码定点加减法所需的硬件配置
寄存器 A、X、加法器的位数相等,其中 A 存放被加数(或被减数)的补码,X 存放加数(或减数)的补码。当作减法时,由 “求补控制逻辑” 将 X ‾ \overline{\text{X}} X 送至加法器,并使加法器的最末位外来进位为 1,以达到对减数求补码的目的。运算结果溢出时,通过溢出判断电路置 “1” 溢出标记 V。GA 为加法标记,GS 为减法标记。
3. 补码加减运算控制流程
在计算机中,有的机器由硬件乘法器直接完成乘法运算,有的机器内没有乘法器,但也可以进行乘法运算,用软件编程实现。
1. 乘法分析
可通过一个案例来了解计算机中乘法的运算规则,例如:
设 A=0.1101,B=0.1011,求 A×B
可见在乘法运算中通过被乘数 A 多次的左移,然后对四个位积做相加运算就能得到结果
改进为:
可见两数相乘的过程可视作加法和移位(乘 2-1 相当于做一次右移)两种运算
从初始值为 0 开始,作分步运算,则:
上述运算过程可归纳为:
计算机很容易实现这种运算。用一个寄存器存放被乘数,一个寄存器存放乘积的高位,另一个寄存器存放乘数及乘积的低位,再配上加法器及其他相应的电路,就可组成乘法器。
在第一章时就有介绍过运算器的基本组成结构:
在乘法运算中,ACC
寄存器用于存放乘积高位,MQ
寄存器用于存放乘数及乘积低位,X
寄存器用于存放被乘数
2. 原码乘法
原码表示与真值极为相似,只差一个符号,而乘积的符号又可通过两数符号的逻辑异或求得。
(1)原码一位乘运算规则
以小数点为例,设:
[ x ] 原 = x 0 . x 1 x 2 ⋅ ⋅ ⋅ x n [ y ] 原 = y 0 . y 1 y 2 ⋅ ⋅ ⋅ y n [x]_{原} = x_{0}. x_{1}x_{2}···x_{n} \\ [y]_{原} = y_{0}. y_{1}y_{2}···y_{n} [x]原=x0.x1x2⋅⋅⋅xn[y]原=y0.y1y2⋅⋅⋅yn
则: [ x ] 原 ⋅ [ y ] 原 = x 0 ⊕ y 0 . ( 0. x 1 x 2 ⋅ ⋅ ⋅ x n ) ( 0. y 1 y 2 ⋅ ⋅ ⋅ y n ) [x]_{原} · [y]_{原} = x_{0} \oplus y_{0}. (0.x_{1}x_{2}···x_{n})(0.y_{1}y_{2}···y_{n}) [x]原⋅[y]原=x0⊕y0.(0.x1x2⋅⋅⋅xn)(0.y1y2⋅⋅⋅yn)
式中 0. x 1 x 2 ⋅ ⋅ ⋅ x n 0.x_{1}x_{2}···x_{n} 0.x1x2⋅⋅⋅xn 为 x x x 的绝对值,记作 x ∗ x^{*} x∗, 0. y 1 y 2 ⋅ ⋅ ⋅ y n 0.y_{1}y_{2}···y_{n} 0.y1y2⋅⋅⋅yn 为 y y y 的绝对值,记作 y ∗ y^{*} y∗
原码一位乘的运算规则为:
再令 z i z_{i} zi 表示第 i i i 次部分积,上式可写成递推公式:
(2)原码一位乘所需的硬件配置
图中 A、X、Q 均为 n+1 位的寄存器,其中 X 存放被乘数的原码,Q 存放乘数的原码。移位和加控制电路受末位乘数 Qn 的控制(当 Qn =1 时,A 和 X 内容相加后,A、Q 右移一位;当 Qn =0 时,只作 A、Q 右移一位的操作)。计数器 C 用于控制逐位相乘的次数。S 存放乘积的符号。GM 为乘法标记。
(3)原码一位乘控制流程
乘法运算前,A 寄存器被清零,作为初始部分积,被乘数原码在 X 中,乘数原码在 Q 中,计数器 C 中存放乘数的位置 n。乘法开始后,首先通过异或运算,求出乘积的符号并存于 S,接着将被乘数和乘数从原码形式变为绝对值,然后根据 Qn 的状态决定部分积是否加上被乘数,再逻辑右移一位,重复 n 次,即得运算结果
可以用 A=0.1101,B=0.1011,求 A×B
为例,来演示在计算机中是如何进行上述操作的:
符号位通过A、B符号位的异或运算结果决定: 0 ⊕ 0 0 \oplus 0 0⊕0 = 0,所以结果为:0.10001111
(4)原码两位乘
原码两位乘与原码一位乘一样,符号位的运算和数值部分是分开进行的,但原码两位乘是用两位乘数的状态来决定新的部分积如何形成,因此可提高运算速度。
两位乘数共有四种状态,对应这四种状态可得:
双符号位 | 对应情况 | 说明 |
---|---|---|
00 | 正 | |
01 | 下溢 | 如果两个正数都很大,数值位最高位很容易发生向符号位低位的进位 |
10 | 上溢 | 在自然情况下,符号位运算的结果为10,如果两个负数都很小,数值位最高位很难发生向符号位低位的进位/补充 |
11 | 负 |
3. 补码乘法
(1)补码一位乘(Booth 算法)运算规则
和原码一位乘法不同的是,补码一位乘法(Booth 算法)是双符号位,并且符号位也会与数值一起参加运算,直接得出用补码表示的乘积,且正数和负数同等对待,采用补码右移方式,区别于原码乘法的逻辑右移,补码的右移是算术右移。
补码乘法运算规则如下:
yn(高位) | yn-1(低位) | 操作 |
---|---|---|
0 | 0 | 部分积加 0,右移一位 |
0 | 1 | 部分积 +[x]补,右移一位 |
1 | 0 | 部分积 +[-x]补,右移一位 |
1 | 1 | 部分积加 0,右移一位 |
(2)补码比较法(Booth 算法)所需的硬件配置
图中 A、X、Q 均为 n+2 位寄存器,其中 X 存放被乘数的补码(含两位符号位),Q 存放乘数的补码(含最高一位符号位和最末一位附加位),移位和加法控制逻辑受 Q 寄存器末 2 位乘数控制。当其为 01 时,A、X 内容相加后 A、Q 右移一位,当其为 10 时,A、X 内容相减后 A、Q 右移一位,计数器 C 用于控制逐位相乘的次数,GM 为乘法标记。
(3)补码比较法(Booth 算法)的控制流程
以 A=-0.1101,B=0.1011,求 A×B
为例,来演示在计算机中补码乘法是如何进行上述操作的:
可得 [x]补 · [y]补 = 11.011100010,补码 11.011100010 的原码为 :11.100011110,即 1.10001111
(4)补码两位乘
补码两位乘运算规则是根据补码一位乘的规则,把比较 ynyn+1 的状态应执行的操作比较 yn-1yn 的状态应执行的操作合并成一步,便可得补码两位乘的运算方法。
1. 除法分析
以小数为例,设 x = -0.1011,y = 0.1101,求 x/y
笔算过程如下:
其特点可归纳为:
对于计算机而言:
2. 原码除法
原码除法和原码除法一样,符号位是单独处理的。
以小数点为例,设:
[ x ] 原 = x 0 . x 1 x 2 ⋅ ⋅ ⋅ x n [ y ] 原 = y 0 . y 1 y 2 ⋅ ⋅ ⋅ y n [x]_{原} = x_{0}. x_{1}x_{2}···x_{n} \\ [y]_{原} = y_{0}. y_{1}y_{2}···y_{n} [x]原=x0.x1x2⋅⋅⋅xn[y]原=y0.y1y2⋅⋅⋅yn
则: [ x y ] 原 = ( x 0 ⊕ y 0 ) ⋅ ( 0. x 1 x 2 ⋅ ⋅ ⋅ x n ) ( 0. y 1 y 2 ⋅ ⋅ ⋅ y n ) [\frac{x}{y} ]_{原} = (x_{0} \oplus y_{0})\cdot \frac{(0.x_{1}x_{2}···x_{n})}{(0.y_{1}y_{2}···y_{n})} [yx]原=(x0⊕y0)⋅(0.y1y2⋅⋅⋅yn)(0.x1x2⋅⋅⋅xn)
式中 0. x 1 x 2 ⋅ ⋅ ⋅ x n 0.x_{1}x_{2}···x_{n} 0.x1x2⋅⋅⋅xn 为 x x x 的绝对值,记作 x ∗ x^{*} x∗, 0. y 1 y 2 ⋅ ⋅ ⋅ y n 0.y_{1}y_{2}···y_{n} 0.y1y2⋅⋅⋅yn 为 y y y 的绝对值,记作 y ∗ y^{*} y∗
即商符由两数符号位 ”异或“ 运算求得,商值由两数绝对值相除 (x*/y*) 求得。小数定点除法对被除数和除数有一定的约束,即必须满足下列条件:
0 < ∣ 被除数 ∣ ≤ ∣ 除数 ∣ 0 < |被除数| \le |除数| 0<∣被除数∣≤∣除数∣
实现除法运算时,还应避免除数为 0 或被除数为 0。至于商的位数一般与操作数的位数相同。
在除法运算中,ACC
寄存器用于存放被除数及余数,MQ
寄存器用于存放商,X
寄存器用于存放除数
原码除法中由于对余数的处理不同,又可分为恢复余数法和不恢复余数法(加减交替法)两种:
(1)恢复余数法
恢复余数法的特点是:当余数为负时,需加上除数,将其恢复成原来的余数。
设机器字长为 5 位(含一位符号位),x=0.1011,y=0.1101,采用原码恢复余数求 x/y
符号位进行异或操作: 0 ⊕ 0 0 \oplus 0 0⊕0 = 0,结果为:0.1101
(2)加减交替法
加减交替法又称不恢复余数法,可以认为它是恢复余数法的一种改进算法。
通过原码恢复余数法可归纳为:当 Ri > 0,商上 “1”,做 2Ri-y* 的运算;当 Ri < 0,商上 “0”,做 2Ri+y* 的运算。
这里已经看不出余数的恢复问题了,而只是做加 y* 或减 y*,因此,一般把它叫做加减交替法或不恢复余数法。
仍以上述例题为例:设机器字长为 5 位(含一位符号位),x=0.1011,y=0.1101,采用原码加减交替法求 x/y
符号位进行异或操作: 0 ⊕ 0 0 \oplus 0 0⊕0 = 0,结果为:0.1101
(3)原码加减交替法所需的硬件配置
图中 A、X、Q 均为 n+1 位寄存器,其中 A 存放被除数的原码,X 存放除数的原码。移位和加控制逻辑受 Q 的末位 Qn 控制。(Qn=1 作减法,Qn=0 作加法),计算器 C 用于控制逐位相除的次数 n,GD 为除法标记,V 为溢出标记,S 为商符。
(4)原码加减交替除法控制流程
3. 补码除法
与补码乘法类似,也可以用补码完成除法操作。补码除法也分恢复余数法和加减交替法,后者用得较多。
(1)补码加减交替法运算规则
补码除法其符号位和数值部分是一起参加运算的,因此在算法上不像原码除法那样直观,其规则如下:
[Ri]补 与 [y]补 | 商 | 新余数[Ri+1]补 |
---|---|---|
同号 | 1 | [Ri+1]补 = 2[Ri]补 + [-y]补 |
异号 | 0 | [Ri+1]补 = 2[Ri]补 + [y]补 |
因为精度的问题,约定商的末位用 “恒置 1” 的舍入规则。
(3)补码加减交替法所需的硬件配置
补码加减交替法所需的硬件配置与原码加减交替法的硬件配置相似,只是 S 触发器可以省掉,因为补码除法的商符在运算中自动形成。此外,在寄存器中存放的均为补码。
(3)补码加减交替法的控制流程
设机器字长为 5 位(含一位符号位),x=-0.1001,y=0.1101,采用补码加减交替法求 [x/y]补
机器中的任何一个浮点数都可写成:
x = S x ⋅ r j x x=S_{x} \cdot r^{j_{x}} x=Sx⋅rjx
其中, S x S_{x} Sx 为浮点数的尾数,一般为绝对值小于 1 的规格化数(补码表示时允许为 -1),机器中可用原码或补码表示; j x j_{x} jx 为浮点数的阶码,一般为整数,机器中大多用补码或移码表示; r r r 为浮点数的基数,常用 2、4、8 或 16 表示,以下以基数为 2 进行讨论。
设两个浮点数: x = S x ⋅ r j x x=S_{x} \cdot r^{j_{x}} x=Sx⋅rjx 、 y = S y ⋅ r j y y=S_{y} \cdot r^{j_{y}} y=Sy⋅rjy
由于浮点数尾数的小数点均固定在第一数值位前,所以尾数的加减运算规则与定点数完全相同,但由于其阶码的大小又直接反映尾数有效值得小数点位置,因此当两浮点数阶码不等时,因两尾数小数点的实际位置不一样,尾数部分无法直接进行加减运算。因此,浮点数加减运算必须按以下几个步骤进行:
1. 对阶
对阶的目的是使两操作数的小数点位置对齐,即使两数的阶码相等。为此,首先要求出阶差,再按小阶向大阶看齐的原则,使阶小的尾数向右移位,每右移一位,阶码加 1,直到两数的阶码相等为止。右移的次数正好等于阶差,尾数右移可能会发生数码丢失,影响精度。
例如:两浮点数 x=0.1101×201,y=(-0.1010)×211,求 x+y。
在求和前需要先将其阶码同样,x 的阶码使 01,y 的阶码是 11,按小阶码向大阶码看齐的原则,需要将 x 的阶码也转变为 11,就需要将尾数向右移动 2 位(112-012=102=210),即 x’=0.0011×211,但是不难看出 x 尾数右移两位,精度丢失了。
2. 尾数求和
将对阶后的两个尾数按定点加(减)运算规则进行运算。
3. 规格化
尾数 S S S 的规格化形式为: 1 2 ≤ ∣ S ∣ < 1 \frac{1}{2} \le |S| < 1 21≤∣S∣<1
如果采用双符号位的补码,则:
可见,当尾数的最高数值位与符号位不同时,即为规格化形式,但对 S < 0 S < 0 S<0 时,有两种情况需特殊处理:
规格化又分为左规跟右规两种:
4. 舍入
在对阶和右规的过程中,可能会将尾数的低位丢失,引起误差,影响了精度。为此可用舍入法来提高尾数的精度,常用的舍入方法有两种:
5. 溢出判断
在浮点规格化中已指出,当尾数之和(差)出现 01.XX···X 或 10.XX···X 时,并不表示溢出,只有右规后,在根据阶码来判断浮点运算结果是否溢出。
当阶码 [ j ] 补 = 01 , X X ⋅ ⋅ ⋅ X [j]_{补}=01,XX \cdot \cdot \cdot X [j]补=01,XX⋅⋅⋅X 为上溢,需做溢出处理;阶码 [ j ] 补 = 10 , X X ⋅ ⋅ ⋅ X [j]_{补}=10,XX \cdot \cdot \cdot X [j]补=10,XX⋅⋅⋅X 为下溢,按机器零处理。
浮点加减运算流程
两个浮点数相乘,其乘积的阶码应为相乘两数的阶码之和,其乘积的尾数应为相乘两数的尾数之积。两个浮点数相除,商的阶码为被除数的阶码减去除数的阶码,其尾数为被除数的尾数除以除数的尾数所得的商。
设两个浮点数: x = S x ⋅ r j x x=S_{x} \cdot r^{j_{x}} x=Sx⋅rjx 、 y = S y ⋅ r j y y=S_{y} \cdot r^{j_{y}} y=Sy⋅rjy
乘法: x ⋅ y = ( S x ⋅ S y ) × r j x + j y x \cdot y=(S_{x} \cdot S_{y}) × r^{j_{x} + j_{y}} x⋅y=(Sx⋅Sy)×rjx+jy
除法: x y = S x S y ⋅ r j x − j y \frac{x}{y}=\frac{S_{x}}{S_{y}} \cdot r^{j_{x} - j_{y}} yx=SySx⋅rjx−jy
在运算中也要考虑规格化和舍入问题。
1. 阶码运算
若阶码用补码运算,乘积的阶码为 [jx]补 + [jy]补,商的阶码为 [jx]补 - [jy]补,两个同号的阶码相加或异号的阶码相减可能产生溢出,此时应作溢出判断。
2. 尾数运算
(1)浮点乘法尾数运算
两个浮点数的尾数相乘,可按下列步骤进行:
(2)浮点除法尾数运算
两个浮点数的尾数相除,可按下列步骤进行:
针对每一种算术运算,都必须有一个相对应的基本硬件配置,其核心部件是加法器和寄存器。当需完成逻辑运算时,势必需要配置相应的逻辑电路,而 ALU
电路是既能完成算术运算又能完成逻辑运算的部件。
图中 Ai 和 Bi 为输入变量;ki 为控制信号,ki 的不同取值可决定该电路作哪一种算术运算或哪一种逻辑运算;Fi 是输出函数。
如 74181 是能完成四位二进制代码的算逻运算部件
随着操作数位数的增加,电路中进位的速度对运算时间的影响也越大,为了提升运算速度,就有了快速进位链的存在。
所谓进位链就是传送进位的电路。
1. 并行加法器
并行加法器由若干个全加器
组成,如图所示,n+1 个全加器级联就组成了一个 n+1 位的并行加法器。
由于每位全加器的进位输出是高一位全加器的进位输入,因此当全加器有进位时,这种一级一级传递进位的过程,将会大大影响运算速度。
由全加器的逻辑表达式可知:
和: S i = A i ‾ B i ‾ C i − 1 + A i ‾ B i C i − 1 ‾ + A i B i ‾ C i − 1 ‾ + A i B i C i − 1 S_{i}=\overline{A_{i}} \overline{B_{i}} C_{i-1} +\overline{A_{i}} B_{i} \overline{C_{i-1}} + A_{i} \overline{B_{i}} \overline{C_{i-1}} + A_{i}B_{i}C_{i-1} Si=AiBiCi−1+AiBiCi−1+AiBiCi−1+AiBiCi−1
进位: C i = A i ‾ B i C i − 1 + A i B i ‾ C i − 1 + A i B i C i − 1 ‾ + A i B i C i − 1 = A i B i + ( A i + B i ) C i − 1 C_{i}=\overline{A_{i}} B_{i} C_{i-1} +A_{i} \overline{B_{i}} C_{i-1} + A_{i} B_{i} \overline{C_{i-1}} + A_{i}B_{i}C_{i-1}= A_{i}B_{i} +(A_{i}+B_{i})C_{i-1} Ci=AiBiCi−1+AiBiCi−1+AiBiCi−1+AiBiCi−1=AiBi+(Ai+Bi)Ci−1
可见, C i C_{i} Ci 进位有两部分组成:本地进位 A i B i A_{i}B_{i} AiBi ,可记作 d i d_{i} di,与低位无关;传递进位 ( A i + B i ) C i − 1 (A_{i}+B_{i})C_{i-1} (Ai+Bi)Ci−1,与低位有关,可称 A i + B i A_{i}+B_{i} Ai+Bi 为传递条件,记作 t i t_{i} ti 则:
C i = d i + t i C i − 1 C_{i}=d_{i}+t_{i}C_{i-1} Ci=di+tiCi−1
由 C i C_{i} Ci 的组成可以将逐级传递进位的结构,转换为以进位链的方式实现快速进位。目前进位链通常采用串行和并行两种。
2. 串行进位链
串行进位链是指并行加法器中的进位信号采用串行传递。
以 4 位全加器为例,每一位的进位表达式为:
设与非门的级延迟时间为 t y t_{y} ty,那么当 d i d_{i} di、 t i t_{i} ti 形成后,共需 8 t y 8t_{y} 8ty 便可产生最高位的进位。实际上每增加一位全加器,进位时间就会增加 2 t y 2t_{y} 2ty。 n n n 位全加器的最长进位时间为 2 n t y 2nt_{y} 2nty。
3. 并行进位链
并行进位链是指并行加法器中的进位信号是同时产生的,又称先行进位、跳跃进位等。
通常并行进位链有单重分组和双重分组两种实现方案。
四位一组并行进位链逻辑图:
设与或非门的级延迟时间为 1.5 t y 1.5t_{y} 1.5ty,与非门的级延迟时间仍为 1 t y 1t_{y} 1ty,则 d i d_{i} di、 t i t_{i} ti 形成后,只需 2.5 t y 2.5t_{y} 2.5ty 就可产生全部进位。
(1)单重分组跳跃进位
单重分组跳跃进位就是将 n n n 位全加器分成若干小组,小组内的进位同时产生,小组与小组之间采用串行进位,这种进位又有组内并行、组间串行之称。
如果将 16 位的全加器按四位一组分组,便可得单重分组跳跃进位链框图:
当 d i d_{i} di、 t i t_{i} ti 形成后,经过 2.5 t y 2.5t_{y} 2.5ty 可产生 C 3 C_{3} C3、 C 2 C_{2} C2、 C 1 C_{1} C1、 C 0 C_{0} C0 四个进位信息,经 10 t y 10t_{y} 10ty 就可产生全部进位,而 n=16 的串行进位链的全部进位时间为 32 t y 32t_{y} 32ty ,可见单重分组方案进位时间仅为串行进位链的三分之一。
但随着 n n n 的增大,其优势便很快减弱,如当 n=64 时,按四分分组,其为 16 组,组间有 16 位串行进位,在 d i d_{i} di、 t i t_{i} ti 形成后,还需 40 t y 40t_{y} 40ty 才能产生全部进位,显然进位时间太长。
(1)双重分组跳跃进位
双重分组跳跃进位就是将 n n n 位全加器分成几个大组,每个大组又包含几个小组,而每个大组内所包含的各个小组的最高位进位是同时形成的,大组与大组间采用串行进位。
进行分析可将上述表达式进一步展开得:
可见,每小组可产生本小组的本地进位 D i D_{i} Di 和传送条件 T i T_{i} Ti 以及组内的各低位进位,但不能产生组内最高进位。
两种类型的线路可构成 16 位加法器的双重分组跳跃进位链框图:
当 d i d_{i} di、 t i t_{i} ti 及 C − 1 C_{-1} C−1 (外来进位)形成后开始,经过 2.5 t y 2.5t_{y} 2.5ty 形成 C 2 C_{2} C2、 C 1 C_{1} C1、 C 0 C_{0} C0 和全部 D i D_{i} Di、 T i T_{i} Ti;再经 2.5 t y 2.5t_{y} 2.5ty 形成大组内的四个进位 C 15 C_{15} C15、 C 11 C_{11} C11、 C 7 C_{7} C7、 C 3 C_{3} C3;再经过 2.5 t y 2.5t_{y} 2.5ty 形成其余进位,可见,按双重分组设计 n=16 的进位链,最长进位时间为 7.5 t y 7.5t_{y} 7.5ty ,比单重分组进位链又省了 2.5 t y 2.5t_{y} 2.5ty 。
上篇:第五章、输入输出系统
下篇:第七章、指令系统