计组第六章 计算机的运算方法(ALU)
第六章 计算机的运算方法(ALU )
6.1 无符号数和有符号数
6.1.1. 无符号数
没有正负号,就能直接表示,二进制表示接口
如果保存在寄存器中,寄存器的位数反映无符号数的表示范围
6.1.2. 有符号数
有符号数分符号和数值
(*) 概念:机器数与真值
真值就是这个数实际的值,包含符号;机器数就是数字在机器中的表示方式
小数点没有专门的位去表示,它是以约定的形式表示的,比如在浮点数中,符号位后面就是小数点
对于整数,在其绝对值前面加了符号位
(1) 原码表示法
原码表示法实际上是
带符号的绝对值表示,符号是数值化的
① 定义
a. 整数
x为真值,[x]原为机器数
分析
例如
24是因为有4位数据位
b. 小数
注意1,小数是不可能等于1的,因此没有=
分析同整数一样
举例
② 例题
题目
答案
方法1——由定义得
-
注意
方法2——直接得
原码表示法的特点就是直接对符号进行数字化转化即可:
- 原码->真值:符号位符号化,数值位不变
- 真值->原码:符号位数字化,数值位不变
③ 特点
a. 原码优点
- 原码表示法的有点就是简单直观,真值与机器值一眼就能进行转化
b. 原码缺点
但是用原码作加法时,会出现如下问题
-
同样是做加法过程,实际操作可能是加法也可能是减法,对运算器来说比较麻烦
要设计单独的加法运算器和减法运算器
-
能否进行归一化操作,只用加法就能实现减法运算
-
意思就是:找到一个与负数等价的正数 来代替这个负数参加运算
-
就可使 减法 ->加法
总的来说,就是原码进行加法的时候麻烦
(2) 补码表示法
① “补”的概念
我们以时钟来进行举例
- 可以看到 -3这个负数有与其对应的+9整数等价,在补的情况下
结论:
- 一个负数加上 “模” 即得该负数的补数
- 一个正数和一个负数互为补数时,它们绝对值之和即为 模 数
举一个例子,在4位计数器(模16)的情况下,让1011计算得到0000
- 1011+0101 = 10000(也就是16),-1011的补码就是 (10000 - 1011 = 0101)
② 正数的补数即为其本身
两个互为补数的数,分别加上模,结果仍互为补数
- 可见正数的补数就是其本身
问题:
- 正数0101的补数是0101,负数-1011的补数也是0101
- 那么如何区分这是整数还是负数呢?
因此引入符号位,即在补码前面再添加一个符号位
如何实现在补码前面添加符号位呢?
我们之前是一个负数+2n就得到了补码(不含符号位),现在在前面添加一个1,就是说又加了一个2n,总共加了2n+1次
因此有如下的结果
因此可以引出补码的定义
③ 补码的定义
一般使用定义来求补码的写法,但是可以根据定义咋得到补码的时候求得真值
a. 整数
- 这个2n+1+x,不如记成 2n+1-|x|
- 用补码表示整数,最小能表示到-2n
- ±0的补码一样
我们以字长5位(符号1位,数据4位)来举例整数,字长8位举例负数
注意:模是2n+1次方,也就是2字长次方,n是数值位的数目
b. 小数
同样的,2+x不如记成2-|x|
这里是模2,也可以模4,模8,这样的话小数点前面就有2位,3位了
④ 补码原码转换的快捷方式(获得补码的方式)
a. 原码(真值) ——> 补码
正数的补码就是其本身,因此下面只讨论负数
下面是推导
结论
负数的补码,就是保持符号位不变,其余各位取反,最终末位+1
真值和原码也很好转换的,就是数字位前面+1
下面是例子
b. 补码——> 原码(真值)
符号位变,每位取反,末尾+1,末尾+1也不改变符号位
c. 练习
再看下面的,±0的补码是不一样的
以及注意,补码源码不一定能够相互转化,因为补码比原码多出一位数据可以表示2n
d. 更简单的方法
补码和原码的转换有个更简单的方法,当然是在负值的情况下
保持符号位不变,数值位找到最右边的第一个1,这个1及其后面的0不变,前面的全部取反(取反的过程中符号位不变)
整数和小数同样适用
以下就是负数补码的结果
⑤ 补码特点
a. 补码优点
- 就是能够将减法转化成加法,机器运算的时候更加简单
b. 补码缺点
-
补码表示很难直接判断其真值大小
⑥ [y]补与[-y]补的转化
-
y为正数
-
y为负数
总结:
- [y]补连同符号位在内,每位取反,末尾+1,得到[-y]补
- 其实也就是找到右边的第一个1,左边的所有位取反,包括符号位
(3) 反码表示法
- 补码是 符号位不变,数值位取反,末尾+1
- 反码是 符号位不变,数值位取反,不+1
① 反码的定义
a. 整数
- x<0时,可以记作 (2n+1 - 1) - |x|
- 反码也是不能表示 -2n
- (2n+1 - 1)的二进制形式就是n个1
b. 小数
2-2-n就是1.1111(1后面跟着n个1,n位小数部分,也就是数值位的位数)
② 例题
- 正数的反码仍然是其本身
- 负数的反码就是符号位不变,数值位取反
±0的反码不同的
(*) 三种机器数的小结
-
最高位为符号位,书写上用“,”(整数)或“.”(小数)将数值部分和符号位隔开
但是在存储的时候不用
-
对于正数,原码 = 补码 = 反码
-
对于负数 ,符号位为 1,其 数值部分
- 原码除符号位外每位取反末位加 1 补码
- 原码除符号位外每位取反 反码
表示范围(以8位为例)
- 设机器数字长为 8 位(其中1位为符号位) 对于整数,当其分别代表无符号数、原码、补码和 反码时,对应的真值范围各为多少?
(4) 移码表示法
上述可知,补码很难直接判断其真值的大小
补码的定义如下
x + 2n+1,但是如果改成 2n,结果就会不同
这就是移码
① 移码的定义
[x]移 = 2n + x(2n>x ≥ 2n)x 为真值,n 为 整数的位数
不论是整数还是负数,都是这个样子,当然可以记作 x < 0时,[x]移 = 2n - |x|
移码和真值的对应关系图如下
可以看到,移码相当于真值全部右移2n
注意:
- 不论是整数还是负数,定义都为[x]移 = 2n + x(2n>x ≥ 2n)
- 只有整数的定义,没有小数的定义,这与移码的功能有关
- 通常情况下,移码一般表示浮点数据的解码部分
② 移码和补码的比较
补码与移码只差一个符号位
真值、补码和移码的对照表
③ 移码的特点
- [+0]移 = [ 0]移
- 最小真值的移码为全 0
- 用移码表示浮点数的阶码,能方便地判断浮点数的阶码大小
6.2 数的定点表示和浮点表示
6.2.1. 定点表示
(1) 定义
定点表示是指,小数点的位置按照约定的形式给出
有两种约定的方式
第一种方式:小数点在符号位的后面
- 这种方式下,存储或者操作的数据都是小数
- 补码可以表示唯一的整数-1
第二种方式:数值部分的最后
- 计算机的定点数都是整数
据此,可以将计算机分为两类:小数定点机和整数定点机
定点表示的范围
小数定点机 | 整数定点机 | |
---|---|---|
图解 | ||
原码 | -(1 - 2-n) ~ +(1 - 2-n) | -(2n - 1) ~ +(2n - 1) |
1.11..11 ~ 0.11..11 | 1.1..11 ~ 0.11..11 | |
补码 | -1 ~ +(1 - 2-n) | -2n ~ +(2n - 1) |
1.00..00 ~ 0.11..11 | ||
反码(和原码的形式相同) | -(1 - 2-n) ~ +(1 - 2-n) | -(2n - 1) ~ +(2n - 1) |
(2) 定点表示的缺点
由于早期硬件的限制,只能使用定点表示
-
编程困难,程序员要调节小数点的位置
-
数的表示范围小,为了能表示两个大小相差很大的数据,需要很长的机器字长;
例如:太阳的质量是0.2\1034克,一个电子的质量大约为0.9*10-27克,两者的差距为1061以上,若用定点数据表示:2x>1061,解的,x>203位
-
数据存储单元的利用率往往很低。
就拿上面的例子来说,很多数字都达不到那么大的,很多数值都被浪费了
因此引入了下面的浮点数
6.2.2. 浮点表示(重点)
浮点数的一般形式
- S 尾数,是小数,可正可负,|S| < 1
- j 解码,整数
- r 尾数的基值,计算机中 r 取 2、4、8、16 等
- 如果r = 4,在S中每两位表示一位四进制数
- 如果r = 8,S中每三位表示一位八进制数
- S只能是小数,并且只能小于1
- 小数点后数值位第一位是1的形式叫做规格化数
r基数提前约定好,那么我们只需要保存 尾数S 和 阶码j 即可
(1) 浮点数的表示形式
- Sr:代表浮点数的符号
- n尾数长度:其位数反映浮点数的精度
- m解码长度:其位数反映浮点数的表示范围
- jr和m:共同表示小数点的实际位置
总之大小由解码和尾数共同决定
(2) 浮点数的表示范围
我们以原码表示尾数和阶码的方式举例
-
阶码的绝对值最大是1111,表示2m - 1,那么阶码的范围就是±(2m - 1),这是基数的指数,基数为2
-
尾数的数值部分,也就是0.几后面的几的部分,所以S就表示的不大的部分
尾数绝对值最大的情况,S全为1,就是 1 - 2-n
尾数绝对值最小且不为0的部分,S最后一位为1,那就是 2-n
尾数最小的就全是0,那就是0
我们以阶码位数为4,尾数位数为10来看看
此时总共有16位,有216种数据,就要用这么多数据来表示这个范围里面的所有数
还有两个概念
- 上溢:阶码 > 最大阶码,按照错误处理
- 下溢:阶码 < 最小阶码 按 机器零 处理,就是这种情况就是按照0处理
都是看的阶码,因为阶码决定的是范围
练习:根据表示范围确定阶码尾数位数
精度最大,表示尾数要最多,n = 18是最多的
机器0的表示
- 当浮点数 尾数为 0 时,不论其阶码为何值按机器零处理
- 当浮点数 阶码等于或小于它所表示的最小数 时,不论尾数为何值,按机器零处理
我们以 阶码位数m=4,尾数位数n=10来举例
阶码用移码,尾数用补码表示,有利于机器中“ 判 0 ” 电路的实现
(3) 浮点数的规格化形式
① 使用浮点数的目的
尽可能的保证浮点数的精度,如果不进行规格化,那么小数点后面可能有若干个0,超出尾数的部分会被忽略掉,严重降低精度
为了保证精度,我们要有效位尽可能的多
② 形式
规格化要求尾数真值的最高位不能为0
- r = 2,尾数最高位为 1
- r = 4,尾数最高 2 位不全为 0
- r = 8,尾数最高 3 位不全为 0
基数不同,浮点数的规格化形式不同
(4) 浮点数的规格化
基值r | 左规 | 右规 |
---|---|---|
r = 2 | 左规 尾数左移 1 位,阶码减 1 | 右规 尾数右移 1 位,阶码加 1 |
r = 4 | 左规 尾数左移 2 位,阶码减 1 | 右规 尾数右移 2 位,阶码加 1 |
解释一下,尾数的2位 表示 41 | ||
r = 8 | 左规 尾数左移 3 位,阶码减 1 | 右规 尾数右移 3 位,阶码加 1 |
-
左规右规的最终结果是
尾数真值的最高位不能为0
-
无论怎样,阶码都是移动1位
基数 r 越大,可表示的浮点数的范围越大,浮点数的精度降低
因为r越大,阶码的位数不变,最终 rj表示的范围越大
r越大,尾数的位数不变,多位数字只能表示一位真值
6.2.3. 例题
在浮点机中,机器数的表示形式是 阶码;尾数
6.2.4. IEEE754标准
- 尾数为规格化表示,也就是尾数真值的最高位必须为1,这样就可以不用保存尾数第一位了,这样可以有更多位保存尾数,提高精度
IEEE754标准有以下几种实数
符号位S | 阶码 | 尾数 | 总位数 | |
---|---|---|---|---|
短实数 | 1 | 8 | 23 | 32 |
长实数 | 1 | 11 | 52 | 64 |
临时实数 | 1 | 15 | 64 | 80 |
6.3 定点运算
尽管现代计算机不使用,但是使用的浮点数的计算基础也是定点数的计算
6.3.1. 移位运算
(1) 移位运算的数学意义
我们以单位转换来举例
15.m = 1500.cm,这相当于小数点右移了2位
但是在计算机中是没有小数点的,只能移动数据,可以说成15相对于小数点 左移2位
,表示扩大
在计算机中:
- 左移——绝对值扩大(在计算机中扩大一倍)
- 右移——绝对值缩小
在计算机中,移位与加减配合,能够实现乘除运算
(2) 算数移位规则
要保证 符号位不变
,也就是移位仅仅是数值位移动,符号位不动
的
码制 | 填补位 | 说明 | |
---|---|---|---|
正数 | 原码、补码、反码 | 0 | 正数 原码反码补码都一样,都和原码一样添0 |
负数 | 原码 | 0 | 负数的话,就对应着正数来,负数的原码和正数原码的数据位相同,因此和正数一样 |
补码 | 左移添 0 | 在负数补码中,右侧的0还是原码中右侧的 0 |
|
右移添 1 | 左侧的1相当于原码的0 |
||
反码 | 1 | 负数反码的1相当于原码的0 |
例题
(3) 算术移位的硬件实现
正数 | 负数原码 | 负数补码 | 负数反码 | |
---|---|---|---|---|
左移 | ||||
右移 |
- 左边的小框框表示符号位,一直自我循环更新,表示符号位不变
- 右边的长框框表示数据位,移位就是移数据位
- 负数的反码的符号位就是1,反码就是所有位全部取反
移位丢1的影响
对于真值,也就是正数的数据位,如果左移右移丢的都是0的话,得到的结果是正确的
正数 | 负数原码 | 负数补码 | 负数反码 | |
---|---|---|---|---|
左移 丢1 | 出错 | 出错 | 正确 | 正确 |
右移 丢1 | 影响精度 | 影响精度 | 影响精度 | 正确 |
-
出错不是报错,是指左移本该×2,出错是指结果不是预期的
-
负数原码的 数据位 和正数的 数据位 一样,所以结果一样
-
负数补码 左侧的1对应真值的0,丢1相当于丢0;右侧的1相当于原码的1,丢1相当于丢1
如果补码是丢0的话,就会出问题
-
负数的反码的1就是正数的0,丢0结果都正确
(4) 算术移位和逻辑移位的区别
操作对象 | ||
---|---|---|
算数移位 | 有符号数 | 有符号数的移位,移位只移数据位 |
逻辑移位 | 无符号数 | 无符号数的移位,所有位都要移动 |
操作 | 图示 | |
---|---|---|
逻辑左移 | 低位添 0,高位移丢 | |
逻辑右移 | 高位添 0,低位移丢 |
逻辑移位都是添0的
6.3.2. 加减法运算
我们在讨论原码计算缺点的时候,知道加法减法要分别设计不同的运算器
因此我们引入了补码的概念:正数的补码就是原码,负数的补码是其对应的正数,由于机器运算有取模的性质,因此当加法超过范围的时候,就会忽略掉最高位,用这种性质将减法变成加法
以下讨论的加减法都是指 补码的加减法
(1) 补码加减运算公式
加法:
公式 | |
---|---|
整数 | [A+B]补 = [A]补 + [B]补(mod 2n+1) |
小数 | [A+B]补 = [A]补 + [B]补(mod 2) |
减法:A–B= A+(–B )
公式 | |
---|---|
整数 | [A-B]补 = [A]补 + [-B]补(mod 2n+1) |
小数 | [A-B]补 = [A]补 + [-B]补(mod 2) |
证明:正数的话一样,负数的话可以将 [X]补 = 2n+1 + [X]原,这样就很好证明了
运算时连同符号位一起相加,符号位产生的进位自然丢掉
不要将减法和与负数的加法混淆在一起
与负数的加法也是直接加的
例题
例一
例二
以上两个例题看似正确:它们没有考虑计算机中寄存器的长度
例三
±y补码的转化就是找到最右边的1,其左边的所有位(包括符号位)都取反
我们来看看下面的问题
二者的结果都超出了范围,因此会出错,这就是溢出
(2) 溢出判断
这部分的原理还是没搞懂
分析:
对于真值来说:
- 同号相减,异号相加都是不会发生溢出的,因为操作数本身就比原来的小
- 同号相加,异号相减才会溢出
但在机器数中,不会出现减法操作,因此如下定义:
- 参加操作的 两个数(减法时即为被减数和“求补” 以后的减数)符号相同,其结果的符号与原操作 数的符号不同,即为溢出
① 一位符号位判溢出
结论:
最高有效位的进位 ⊕ 符号位的进位 = 1,表示溢出
分析:
-
如果一个整数和一个负数相加(是相加,所以负数不用取反求补),其补码的符号,一个是1,一个是0,结果如果溢出,那么会有一个1上来,那么符号位的进位是1,最高位的有效位也是1,因此不是溢出?
-
这里分析不是很懂
以下是硬件的实现机制
计算 | 结果 | 分析 |
---|---|---|
1 ⊕ 0 = 1 | 有溢出 | 第一个1表示最高位有效位的进位是1,第二个0表示符号位的进位是0,表示两个正数相加,两个符号都是0,数据位进上1来符号位也不进位,说明溢出 |
0 ⊕ 1 = 1 | 有溢出 | 最高有效位没有进位,但是符号位进位是1,表示两个负数相加 |
0 ⊕ 0 = 0 | 无溢出 | 相同符号相加且不溢出 |
1 ⊕ 1 = 0 | 无溢出 | 不同符号相加,不会溢出 |
这种方法需要硬件记录 最高有效位的进位 以及 符号位的进位,然后进行异或操作
这是一位符号位的判断方法
② 两位符号位判溢出
先来看看两位符号数的机器数表示,以小数为例
最终的结果就是:
-
小数:
-
正数,符号位是00,数据位就是真值
-
负数,符号位是11,保持符号位不变,数据位为原码所有位取反,末尾加一
也可以找到最右侧的第一个1,其左边所有的位全部取反,符号位不变
可以看成是 100.000 - |x|,因为 0 < |x| <= -1,因此小数点前的两位都是1
-
-
整数:
- 正数,符号位两位0
- 负数同小数负数
判断:
最高符号位 代表其 真正的符号
计算机中补码好像都是用2位符号位?
(3) 补码加法的硬件配置
结构分析:
-
加法器就是ALU,实现加法
-
A是ACC,保存
被加数
或者减数
-
X是X寄存器,保存
加数
或者被减数
-
A、X 均 n+1 位
-
GA为1,表示进行加法操作
-
GS为1,表示减法操作,这个时候会通过求补控制对X中的数据进行求补,只需要在加法器和X之间加个取反即可
然后再对加法器中的进位置一,就实现了末尾+1的操作
6.3.3. 乘法运算
(1) 笔算乘法
先分析笔算除法进而得到计算机中的乘法,计算机的乘法更简单,因为只有二进制数
① 笔算乘法竖式
例题:已知 A = -0.1101, B = 0.1011,求A × B
结果是
A×B = – 0.10001111, 乘积的符号心算求得
我们分析这个运算过程的细节,以及思考其如何在计算机中实现
笔算特点 | 计算机如何实现 |
---|---|
符号位单独处理 | 使用异或门操作乘数与被乘数的符号 |
乘数的某一位决定是否加被乘数 | 将乘数放在一个移位寄存器中,判断最小的移位,如果是1,则+被乘数,否则+0,然后移位 |
4个位积一起相加 | 多次累加,累加的时候注意移位 |
乘积的位数扩大一倍 | 用两个寄存器存储结果 |
② 分析笔算乘法
下面分析 如何通过 加法 和 移位 完成乘法操作
- 之前竖式的是部分积一直左移最后相加
- 现在是每+一次将当前累加的结果右移一位来代替部分积的左移
③ 改进笔算乘法
将部分积右移的低位存到乘数中,是因为实际的机器就是这样存储的
④ 小结
特点:
-
乘法 运算可用
加
和移位
实现,n = 4,加 4 次,移 4 次 -
由乘数的末位决定被乘数是否与原部分积相加
然后 ——>(右移)1 位形成新的部分积,同时 乘数 ——>(右移)1 位(末位移丢),
空出高位存放部分积的低位
(这也是为什么在上面的竖式中要将部分积的累加结果的低位存到乘数中了,因为实际上机器字就是将这一部分存到乘数中的)。 -
被乘数只与部分积的
高位
相加
硬件:
-
3个寄存器
- X:被乘数
- MQ:乘数以及累加和的低位
- ACC:累加和的高位
其中2个具有移位功能:指的是部分积的高位 和 乘数以及部分积的低位
-
1个全加器,需要n+1位,+1是符号位,不是2n+1,因为只用和高位相加
(2) 原码乘法
① 原码一位乘运算规则
以小数为例
总的来说就是数值位进行绝对值相乘,符号位进行异或
二者单独计算,最终合成结果
② 原码一位乘递推公式
上面的这些都不重要,看例题就对了
③ 例题(重点)
已知 x = – 0.1110 y = 0.1101 求[x • y]原
-
符号位的运算:x0 · y0 = 1 ⊕ 0 = 1
-
数值部分的运算
右移操作采用逻辑右移,因为使用的是绝对值计算,也就是无符号数计算,移位就是逻辑移
-
结果:x*• y* = 0. 1 0 1 1 0 1 1 0
[x • y]原 = 1. 1 0 1 1 0 1 1 0
原码乘法特点
-
绝对值运算
-
用移位的次数判断乘法是否结束
最终要再移一位,将乘数的全部的值都给移出去,前面用0补上(无所谓,最后补的0是符号位,符号位是单独计算的)
不是用加法的次数控制是否结束
,因为不一定都要进行加法,但是一定进行移位 -
逻辑移位
:移位的时候前面补0
④ 原码一位乘的硬件配置
结构分析:
结构 | 分析 |
---|---|
A(ACC) | n+1位,其最高位(也就是竖式中小数点前面的一位)保存的不是符号位,而是小数点后面的低位相加之后的进位 最终的符号位是单独计算的 |
X | 被乘数,计算过程中不变 |
Q(MQ) | 可以移位,一开始是乘数,计算过程中乘数一直右移,累加和的低位部分也占据了乘数的高位部分;知道右移n次,乘数完全被累加和的低位占据 |
计数器C | 记录移位的次数,即数值位的长度n |
S | 符号位,通过异或两个数据的符号位得到结果的符号位 |
GM | 乘法的标志 |
移位和加控制 | 控制A和Q进行移位,控制加法器进行加法 这个控制由乘数当前最低位,也就是Q的第n位决定: 如果是1,则控制门打开,被乘数被送到加法器,和部分积的高位累加 如果是0,控制门直接将0送进去,或者干脆不加0,直接进行移位操作 |
(3) 补码乘法
① 补码一位乘运算规则
以小数为例
- 被乘数任意,乘数为正
-
与原码乘相似
但 加 和 移位 按 补码规则 运算
- 补码的加法 [x + y]补 = [x]补 + [y]补
- 移位:就是算数右移,因为不是进行绝对值运算,保证符号位不变,算数右移,而且右移的话添加的是1,相当于原码的0;
-
乘积的符号自然形成
不是进行绝对值运算
-
被乘数任意,乘数为负
乘数[y]补,去掉符号位,操作同 1
最后 加[–x]补,校正
补码运算不是绝对值运算,符号单独计算的
以上两种方法还得分类讨论乘数的正负,比较麻烦,因此引入了下面的方法
② Booth算法
上面的意思就是 (yi+1 - yi)的值决定 [±x]补的选择,不论结果是多少,都要右移
Booth 算法递推公式
上面的都看不懂,关键看下面的
yi+1 | yi | yi+1 - yi | 操作 |
---|---|---|---|
0 | 0 | 0 | 右移一位 |
0 | 1 | 1 | +[x]补,右移一位 |
1 | 0 | -1 | +[-x]补,右移一位 |
1 | 1 | 0 | 右移一位 |
③ 例题(重点)
题目:已知 x = +0.0011 y = – 0.1011 求[x·y]补
最终的结果就是11.11011111,符号自然计算得出来了
④ Booth算法的硬件配置
结构分析:大都和原码乘法的结构一样,这里只说不一样的
结构 | 分析 |
---|---|
ACC | n+2位,2位是符号位 |
Q(MQ) | 存放乘数,可以移位,n+2位,1位符号位,1位是多出来的1位 |
X | n+2位,被乘数,双符号位 |
移位和加控制逻辑 | 根据Q的n和n+1位来决定加[±x]补还是0,然后控制移位 |
(4) 乘法小结
- 整数乘法与小数乘法过程完全相同可用 逗号 代替小数点
- 原码乘 符号位 单独处理;补码乘 符号位 自然形成
- 原码乘去掉符号位运算 即为无符号数乘法
- 不同的乘法运算需有不同的硬件支持
6.3.4. 除法运算
(1) 笔算除法
二进制的除法比十进制的简单多了,因为上商只用上1或者是0
① 分析笔算除法
x = – 0.1011 y = 0.1101 求 x ÷ y
x÷y = – 0. 1 1 0 1,余数 0. 0 0 0 0 0 1 1 1
特点:
特点 | 机器实现 |
---|---|
商符单独处理 | 符号位异或操作 |
心算上商 | ? |
余数不动低位补“0” 减右移一位的除数 | ?余数长度会一直变长,除数右移也会变长,最终需要的计算器的长度增长 |
上商位置不固定 | ? |
② 笔算除法和机器除法的比较
特点 | 机器实现 |
---|---|
商符单独处理 | 符号位异或操作 |
心算上商 | |x |– |y |> 0 上商 1;|x |– |y |< 0 上商 0 |
余数不动低位补“0” 减右移一位的除数 | 余数 左移一位 低位补“0” 减 除数 |
2 倍字长加法器 | 1 倍字长加法器(因为不需要除数右移,余数增长了) |
上商位置不固定 | 在寄存器 最末位上商 |
(2) 原码除法
以小数为例(整数一样,只是将 . 改成 ,即可)
约定:
-
小数定点除法 x* < y*,整数定点除法 x* > y*
因为小数定点除法,结果只能是小数,即不超过1;同样的,整数的除法结果同样是整数
因此做出规定,否则结果会溢出
-
被除数不等于0,如果等于0,直接写答案0
-
除数不能为0
① 恢复余数法
机器字长是5位,符号1位,数据4位
需要-y,所以需要计算 -y的补码
-
符号位单独计算
-
数值部分计算
结果为 0.1101, 余数为 0.0111
注意:
-
上商5次,因为商有5位数
-
第一次上商判溢出,如果溢出,说明小数定点运算中除数大于被除数,溢出了
-
恢复余数,移位4次
-
移位都是逻辑移位,因为操作的都是绝对值
-
余数为正 上商 1,然后左移
-
余数为负 上商 0,恢复余数+[y]补,然后左移
然后继续 -[y*]补
② 加减交替法(不恢复余数法)
这是对恢复余数法的改进,不用恢复余数了,因此是不回复余数法
来分析一下恢复余数法的运算规则
- 余数Ri > 0,上商“1”,然后左移一位,然后 -y*,即2Ri - y*
- 余数Ri < 0, 上商“0”,恢复余数+y*,然后左移一位,然后 -y*,即2(Ri + y*) - y* = 2Ri + y*
不回复余数法的运算规则
-
上商“1” 2Ri – y*
-
上商“0” 2Ri + y*
可以看到,无论怎样都有2Ri,也就是将余数左移2位;
根据上商的值,然后确定±y*,因此称为加减交替法
注意,在恢复余数法中,是先上商,然后进行下一步的 +[±y],因此这里也是一样,可以先上商,再确定±y,余数一定左移
例题:
解法
结果
- 符号位单独计算,为0
- 数值位商为 0.1101,余数为0.0111
- 结果就是 0.1101
特点:
-
上商 n+1 次
-
第一次上商判溢出
如果是1,表示运算结果溢出,对于小数来说,是除数大于被除数,就不用算了
-
移 n 次,加 n+1 次,这是固定的
-
用
移位的次数
判断除法是否结束
(3) 原码加减交替除法硬件配置
结构分析
结构 | 分析 |
---|---|
A(ACC) | n+1位,保存被除数和余数 |
X | n+1位,除数 |
Q(MQ) | 商n+1位,加减交替法,最后一次上商的结果来控制移位和加控制逻辑,从而控制下一步怎么做 |
移位和加控制逻辑 | 判断下一步是 加 还是 减,并且进行移位 |
计数器C | 移位的次数n 或者加法的次数n+1 |
GD | 表示进行除数运算 |
S | 符号位 |
V | 是否发生溢出 |
6.4 浮点运算
之前已经学过了 浮点表示
和 定点运算
,这节在这两个的基础上学习浮点运算
这里只讲解浮点的加减法运算,乘除法运算简单
加减法运算涉及到对阶,因此比乘除法要难
6.4.1. 浮点加减运算
x = Sx · 2jx,y = Sy · 2jy
浮点数都是用补码的形式表示的
(1) 对阶
讲解过程中,假设基值为2
- 两个浮点数进行加减法操作的话,要求其阶必须相同。
- 在基值相同的情况下,如果阶码不同,那么必须对阶码j进行调整,同时要对尾数S进行调整
- 笔算的时候可以心算,计算机中采用加减法来计算阶码移位的次数
求阶差
对阶原则:小阶向大阶看齐
- 也就是小阶要一直+1,知道加到大阶;同时尾数S右移
如果大阶向小阶看起的话,那么大阶-1,同时尾数S左移,在左移的过程中,S前面的真值部分的1就可能移出去,造成错误,因此S不能左移
可以用这一点,在对阶的时候快速判断S是左移还是右移,S只能右移
但是右移会造成精度的损失,后面有处理方法
(2) 尾数求和
阶码相等了尾数就能直接求和(补码保存只用求和)了,直接看例题
例题
例题:x = 0.1101 × 201,y = (–0.1010) × 211,求 x + y
我们假设尾数5位,尾符1位;阶数4位,阶符2位;
机器数用补码的形式表示
-
对阶
对阶的结果如此,但是会发现,x的精度损失了
-
尾数求和
又出现了问题:结果不是规格化的
问题:
- 精度损失
- 结果不是规格化的
(3) 规格化
① 规格化的原因
尽可能地提高在计算机中浮点数的表示精度,把计算机中能表示数据的硬件资源,尽可能的表示出来
总的来说,提高精度,而不是提高表示范围
② 规格化数的定义
之前学过浮点数的规格化形式
简而言之,就是让尾数的小数点后面的真值的第一位不为0
- r = 2,则为0.1xxxx
- r = 4,则为00.01xx,00.11xx,00.10xx
- 等等
然后此处给出了范围的定义
- 如果r = 4,将1/2换成1/4
- 注意1/2是可以取到的,0.100000就是了
- 但是1是取不到的,因为定义就是小于1的小数
但是我们一般不使用定义来判断是否规格化,而是用下面的方法
③ 规格化数的判断
根据定义得到规格化的判断方式
S>0 规格化形式 | S<0 规格化形式 | |
---|---|---|
真值 | 0.1××...× | – 0.1××...× |
原码 | 0.1××...× | 1.1××...× |
补码 | 0.1××...× | 1.0××...× |
反码 | 0.1××...× | 1.0××...× |
分析:
- 正数的原码反码补码都相同,因此从规格化形式相同
- 负数的规格化,符号位都为1
- 原码的数据位和真值相同,一样
补码左边的0和反码的0都相当于原码的1
,因此都是0
- 计算机中采用补码来保存
- 不论整数还是负数,补码的规格化都是:
符号位和数据位的最高位不同
- (谨记这一点,即使是1.1001也不是规格化的,因为在补码中,数据位左侧的1相当于原码的0,可以省去的)
- 可以采用异或门来判断
不使用定义判断规格化是因为有如下的特例
特例
-
由定义得,1/2 <= |S|,但是如果用定义判断的话
1/2就是规格化的,这没问题
但是-1/2也会被认为是规格化的,但实际上不是规格化的
-
S = -1原码是不能表示的,但是补码可以表示
④ 规格化的方式
a. 左规
简而言之:
- 尾数左移,使尾数规格化;尾数扩大2倍
- 阶码-1,因为尾数扩大了
定义:尾数左移一位,阶码减 1,直到数符和第一数位不同为止(因为机器数采用补码表示)
举个例子(就是上面的例题)
[x+y]补 = 00, 11; 11. 1001
- 数据位最高位1和符号位1相同,不是规格化
- 左规1为,阶码-1:[x+y]补 = 00, 10; 11. 0010
- x + y = (– 0.1110)×210
- 对于补码,不要认为其数据位最高位是1就不敢左规忽略,因为对于补码,其左侧的1就相当于原码的0
- 左移是算数移位,符号位不动的
b. 右规
-
尾数右移,阶码+1
-
右规的时机:当 尾数溢出( >1),即即尾数出现 01. ××..×或 10. ××..×时,需 右规
01.和10.出现的时机
01.xxx:0是符号位,1是数值位的最高位;两个正数相加,符号位都为00,当数据位的和超过1之后,就会溢出一位1,从而形成01
10.xxx:1是符号位,0是数值位的最高位;两个负数相加,符号位都为11,由于是补码相加,补码左侧的1就相当于原码的0,因此如果补码数据位之和溢出的话,那么溢出的就是0,11 + 11 得到的结果就是10,因此判溢出
-
这个移动是逻辑右移,符号位跟着移动
-
前面补充的位就是符号位
⑤ 例题(学习)
采用补码操作的话,符号位都取2位
(4) 舍入
- 在
对阶
和右规
过程中,可能出现尾数末位丢失
引起误差,需考虑舍入来减小误差
有两种方法:
- 0舍1入法
- 末位横置1法
实际上还有很多方法,可以自己查看,在考试的时候可以看
例题
(5) 溢出判断
- 现在讲的不是尾数溢出,因为尾数溢出之前已经采用右规的形式判断过了
- 这里判断的是整个浮点数的溢出
计算机表示的数据是离散的,如果要表示的值不在这些离散的数的集合中,要用近似的值来代替
- 设机器数为补码,尾数为 规格化形式,
- 假设阶符取 2 位,阶码的数值部分取 7 位;数符取2 位,尾数取 n 位
- 则该 补码 在数轴上的表示为
注意,补码可以表示-1,就是 11.00000;也可以表示 -2n,就是11;00000...
范围/点 | 机器数表示 | 阶码真值 | 尾数真值 | 真值/处理 |
---|---|---|---|---|
最小负数 | 00,1111111;11.00..0 | 127 | –1 | 2127×(–1) |
最大负数 | 11,0000000;11.011..1 | -128 | 2-1+ 2-n | – 2-128×(2-1+ 2-n) |
最小正数 | 11,0000000;00.100..0 | -128 | 2-1 | 2-128×2-1 |
最大正数 | 00,1111111;00.11..1 | 127 | 1–2-n | 2127×(1–2-n) |
上溢 | 01, ××···× | 超出最大范围,当做错误处理 | ||
下溢 | 10, ××···× | 按照0处理 |
此处的上溢和下溢与尾数的01,10要区别开来
尾数的上溢下溢是可以采用右规的形式解决的,阶码不行
尾数的上溢下溢说的是超出了最大的正负范围;
此处的上溢下溢指的是阶码绝对值超出了其绝对值最大范围,最终使得整个浮点数超出了最大表示范围,或者小于最小表示范围(接近于0)
6.4.2. 浮点乘除运算(略)
6.5 算数逻辑单元
前面我们学习了很多运算电路,它们集成在一起就构成了算数逻辑单元,我们主要介绍ALU电路,而且内部组件已经在前面介绍过了,这里只介绍其外特性
ALU:arithmetic logic unit
6.5.1. ALU 电路
-
Ai Bi:参与运算的两个数
-
Fi:输出
-
Ki:决定参与什么运算(ALU可以实现多种运算)
ALU是一个组合逻辑电路,意思是输入消失后,输出也会消失,因此不具有保存功能;
一般在A B F端接一个寄存器进行保存
有一个例子 四位ALU 74181,可以查看
6.5.2. 快速进位链
这里我们以加法器为例,其他运算可以自己查看学习
(1) 并行加法器
这是我们在数电中学过的,由n+1个全加器构成,叫并行加法器是因为A B 的 n+1个位可以并行的传输到全加器中
- Ai,Bi,输入参与运算的位
- Ci-1:第i个运算器上一位结果的进位
- Si:本位加法的结果
一般来说,Si很好得
- ABC中有奇数个1,结果就为1
- 但是现在的问题是,Si必须得等到Ci-1才能计算得出
因此计算Ci的值
-
AiBiCi-1中有偶数个1或者3个都是1,则进位,化简得到下面的式子
-
可以看到
AiBi全为1的时候Ci为1
AiBi有一位是1的时候,Ci-1可以传递下去
-
因此定义如下变量
di = Ai Bi 本地进位
ti = Ai + Bi 传送条件
-
则Ci = di + tiCi-1
(2) 串行进位链
进位链:传送进位的电路
也就是在加法过程中,我们将产生进位的电路独立出来
串行进位链:进位以串行的方式传送
以 4 位全加器为例,每一位的进位表达式为
然后设计电路
Ci-1通过2个与非门得到Ci
四个串行起来
可以看到,得到4个进位得通过8个与非门
设与非门的级延迟时间为ty
- 4 位 全加器产生进位的全部时间为 8ty
- n 位全加器产生进位的全部时间为 2nty
由此可见,进位的产生成为了加法器的瓶颈
(3) 并行进位链
要求:n 位加法器的进位同时产生
仍然是以4 位加法器为例
① 先行进位/跳跃进位
我们将式子转化成上面的的,可以看到能够直接获得每一位的进位了
电路图如上,全部用与或非门表示
优点:
-
实现并行,速度快
设与或非门的延迟时间为 1.5ty(与或非的结构比较复杂),
当 di ti 形成后
,只需 2.5ty 产生全部进位
缺点:
- 结构太过复杂,如果是32位的进位的话,那就太复杂了
下面给出两种折中方式(速度和复杂程度折中)
② 单重分组跳跃进位链
学习这个分组的思路,在计组中很多场合都采用分组的方式来进行折中的
n 位全加器分若干小组,小组中的进位同时产生,小组与小组之间采用串行进位
以n=16为例
- 时间折中了,而且结构也折中了
但是还可以改进
a. 速度优化分析
- 为什么单重分组跳跃进位链会比串行进位链好呢?
- 因为上一个组的进位可以同时产生一个小组所有的进位
③ 双重分组跳跃进位链
- n 位全加器分若干大组,大组中又包含若干小组
- 每个大组中小组的最高位进位同时产生。大组与大组之间采用串行进位。
以 n = 32 为例,这里分成了2个大组,每个大组分成4个小组,每个小组有4位
- 比如说,第二大组里面有5 6 7 8小组,第8个小组的进位是 C0C1C2C3,第7个小组的进位是C4C5C6C7
- 然后每个大组中的每个小组的最高位的进位同时得到,3 7 11 15一下得到了
- 然后将第二大组中的最高进位传给第一大组,然后第一大组得到4个进位
折中体现在:
- 前四个小组可以同时得到进位,而不必一个小组得到后另一个小组才能得到
a. 大组进位分析
以第 8 小组为例
- D8 小组的本地进位 与外来进位无关
- T8 小组的传送条件 与外来进位无关 传递外来进位
-
注意,di和ti都是直接通过输入得到的
di = Ai Bi 本地进位
ti = Ai + Bi 传送条件
-
而输入是并行同时传入的,因此di和ti可以并行得到
-
Ti和Di也是通过di和ti得到的,因此所有的Ti和Di也可以并行同时得到
-
结果:C3 C7 C11 C15 可以并行得到
但是这个的前提是要得到C-1,因此不同大组的每个小组的最高位不能得到,本大组需要得到上一个大组的进位
b. 大组 进位线路
以第 2 大组为例
c. 小组 进位线路
以第 8 小组为例,只产生 低 3 位 的进位和 本小组的 D8 T8
- 也就是说,每个小组低三位的进位可以直接得到,前提是得到该小组的Ci-1,如果得不到就只能干等着
- 每个小组的 Di和Ti可以直接得到
- 从而再得到每个小组的最高位的进位(同时得到的)
放到一块去看大组和小组
小组 进位线路 | 大组 进位线路 |
---|---|
d. n =16 双重分组跳跃进位链
当 di、 ti 和C-1形成后
时机 | 产生的变量 | 分析 |
---|---|---|
经 2.5 ty | D5 ~ D8、T5 ~ T8 | Di,Ti只需要di,ti产生,也就是只需要Ai,Bi产生,因此可以直接得到 |
C2、C1、C0 | 第 i 个小组的低位的进位只需要当前小组的 di,ti,Ci-1,也就是Ai,Bi,Ci-1,而Ai,Bi可以直接传入,但是只有第8小组的C-1能直接传入,因此只有第8小组的低位可以直接得到 | |
经 5 ty | C15、 C11、 C7、 C3 | 一个大组中的每个小组的最高位的进位 需要Di,Ti,因此需要等Di,Ti才能得到,但是还需要这个大组的Cn-1 ,因此当C-1传进来并且Di,Ti得到,该大组的所有小组的最高位的进位才能得到 |
经 7.5 ty | C14—C12、 C10—C8 、 C6—C4 | 这三个小组的进位不是直接全部得到的吧,小组低位的进位需要该小组的Ci-1,因此应该是串行得到的 |
可以很清楚的看到,小组最高位的进位是大组中产生的,需要的是D,T,整个大组的C 而低位的进位是小组中产生的,需要的是 d,t,小组自己的 C |
e. n =32 双重分组跳跃进位链
当 di 、ti 形成后
时机 | 产生的变量 |
---|---|
经 2.5 ty | D5 ~ D8、T5 ~ T8 |
C2、C1、C0 | |
经 5 ty | C15、 C11、 C7、 C3 |
经 7.5 ty | C14—C12、 C10—C8 、 C6—C4 |
C31、 C27、 C23、 C19 | |
经1 0 ty | C30—C28、 C26—C24、 C22—C20 |
如果是串行进位链的话,32位要用64ty,而使用双重分组跳跃进位链,就用10ty
f. 速度优化分析
为什么双重分组跳跃进位链比单重分组跳跃进位链的好呢?也就是区别在哪里
-
将di,ti转化成Di,Ti,这个操作是并行发生的,比 单重分组 多了这一步
-
一个
大组的进位
可以同时生成每个小组最高位进位
,这个还不是关键该
大组的最高位的进位
可以当做下一个大组的进位,并且该大组的每个小组的低位的进位还没有计算,因此下一个大组的所有进位
和该大组的每个小组的所有低位进位
可以并行计算