第二章 运算方法和运算器
2.1 数据与文字的表示
2.1.1 数据格式
计算机中常见的数据格式有两种,一是定点数,二是浮点数。表示每一种格式都需要有三个要素:
- 进位计数制
- 定、浮点表示
- 如何用二进制编码
计算机编码方式分别有原码(用于对阶)、补码(用于运算)、反码、移码(用于比较大小)
对阶:是将两个浮点数的小数点对齐的操作
2.1.2 数的机器码表示
真值:实际中表示的数字
机器码:计算机中保存的数字
真值:+10010 原码表示:010010
真值:-10010 原码表示:110010
真值:+0.10101 原码表示:0.10101
真值:-0.10101 原码表示:1.10101
原码转补码:
- 若符号位为0,补码等于原码
- 如符号位为1,符号位不变,其余位取反,末位+1
补码转原码:
- 若符号位为0,补码等于原码
- 如符号位为1,符号位不变,其余位取反,末位+1
移码的表示:
简记:数值位与补码相同,符号位与补码相反
真值加上偏移值,溢出的高位丢弃。
偏移值:假如真值有k位,偏移值为 2 k 2^k 2k
在IEEE754标准中,偏移值为 2 k − 1 2^{k-1} 2k−1
2.1.3 校验码
奇偶校验码
海明校验码
2.2 定点加法、减法运算
2.2.1 定点表示法
定点数只能表示两种数据:
-
纯小数:小数点默认放在首位(符号位)之后,不需要在计算机中专门存储
由于首位是符号位,其余位为数值位。所以正小数的范围 0.00...1 0.00...1 0.00...1~ 0.11...1 0.11...1 0.11...1;负小数的范围 1.11...1 1.11...1 1.11...1 ~ 1.00...1 1.00...1 1.00...1
因为数值位越大,对于负数来说值就越小嘛 -
纯整数:小数点默认放在最后一位之后,不需要专门存储
1.00…0和0.00…0都表示0,所以有正0和负0之分
2.2.2补码加减法
首先加减法的运算都是基于补码。所以我们需要知道这样两个式子:
[
x
+
y
]
补
=
[
x
]
补
+
[
y
]
补
[
x
−
y
]
补
=
[
x
]
补
−
[
y
]
补
=
[
x
]
补
+
[
−
y
]
补
[x+y]_补 = [x]_补+[y]_补 \\ [x-y]_补=[x]_补-[y]_补=[x]_补+[-y]_补
[x+y]补=[x]补+[y]补[x−y]补=[x]补−[y]补=[x]补+[−y]补
那么我们如何才能根据
[
y
]
补
[y]_补
[y]补来求出
[
−
y
]
补
[-y]_补
[−y]补呢?
将 [ y ] 补 [y]_补 [y]补连同符号位在内全部取反,末尾加1就是 [ − y ] 补 [-y]_补 [−y]补
2.2.3 溢出检测
1.单符号位法
当最高有效位产生进位而符号位没有进位(两正数相加产生负数),则为正溢
当最高有效位没有进位而符号位产生进位(两负数相加产生负数),则为负溢
2.双符号位法
就是原来符号位占一位,现在占两位,所以就会出现四种不同的结果:
- 00 正常的正数
- 01 上溢(两个正数相加太大了)
- 10 下溢(两个负数相加太小了)
- 11 正常的负数
我们可以这样记,正常符号位00是正数,那么两个正数相加,如果数值最高位溢出,那么就会往符号位进位就变成了01。
2.3 定点乘法运算(非重点)
2.4 定点除法运算(非重点)
2.5 定点运算器的组成
2.5.1 一位全加器
首先先介绍一下全加器和半加器
- 半加器:不考虑低位进位和向高位进位
- 全加器:考虑低位进位 C i − 1 C_{i-1} Ci−1和向高位的进位 C i C_i Ci
我们ALU的设计都是基于全加器进行设计的。其逻辑表达式如下:
- 和表达式: S i = A i ⊕ B i ⊕ C i S_i=A_i\oplus B_i \oplus C_i Si=Ai⊕Bi⊕Ci
- 进位表达式:
C
i
+
1
=
A
i
B
i
+
(
A
i
⊕
B
i
)
C
i
C_{i+1}=A_iB_i+(A_i\oplus B_i)C_i
Ci+1=AiBi+(Ai⊕Bi)Ci
2.5.2 多位加法器
串行加法器
通过一位全加器,我们可以组成四位串行加法器
在串行加法器中,每一位只有一个全加器,数据逐位串行送入加法器中进行运算。如果有n位数据,那么就需要n次传送,也就是
C
1
=
A
0
B
0
+
(
A
0
⊕
B
0
)
C
0
C
2
=
A
1
B
1
+
(
A
1
⊕
B
1
)
C
1
C
3
=
A
2
B
2
+
(
A
2
⊕
B
2
)
C
2
C
4
=
A
3
B
3
+
(
A
3
⊕
B
3
)
C
3
C_1 = A_0B_0+(A_0\oplus B_0)C_0 \\ C_2 = A_1B_1+(A_1\oplus B_1)C_1 \\ C_3 = A_2B_2+(A_2\oplus B_2)C_2 \\ C_4 = A_3B_3+(A_3\oplus B_3)C_3 \\
C1=A0B0+(A0⊕B0)C0C2=A1B1+(A1⊕B1)C1C3=A2B2+(A2⊕B2)C2C4=A3B3+(A3⊕B3)C3
因为第i位的计算依赖第i-1位的进位,所以运算速度较慢。
并行加法器
我们发现上式
A
0
B
0
+
(
A
0
⊕
B
0
)
C
0
A_0B_0+(A_0\oplus B_0)C_0
A0B0+(A0⊕B0)C0可以替换
C
2
C_2
C2中的
C
1
C_1
C1,也就是
C
2
=
A
1
B
1
+
(
A
1
⊕
B
1
)
(
A
0
B
0
+
(
A
0
⊕
B
0
)
C
0
)
C_2=A_1B_1+(A_1\oplus B_1)(A_0B_0+(A_0\oplus B_0)C_0)
C2=A1B1+(A1⊕B1)(A0B0+(A0⊕B0)C0)
同理
C
3
C_3
C3和
C
4
C_4
C4也可以用低位的进位来表示。由于
C
n
C_n
Cn只与
A
、
B
、
C
0
A、B、C_0
A、B、C0有关,而
A
、
B
A、B
A、B是同时输入进运算器的,这样
C
n
C_n
Cn的产生就和
C
n
−
1
C_{n-1}
Cn−1没关系了,也就打破了串行加法的依赖关系。
我们可看到FA的输入不再有低位的进位,而是通过 A 、 B 、 C 0 A、B、C_0 A、B、C0组合而成。这也就构成了并行进位加法器。
为了便于书写和理解,我们将图中
C
4
C_4
C4的
G
=
A
3
B
3
+
(
A
3
⊕
B
3
)
(
A
2
B
2
+
(
A
2
⊕
B
2
)
(
A
1
B
1
+
(
A
1
⊕
B
1
)
A
0
B
0
)
)
P
=
(
A
3
⊕
B
3
)
(
A
2
⊕
B
2
)
(
A
1
⊕
B
1
)
(
A
0
⊕
B
0
)
\begin{aligned} G & = A_3B_3+(A_3\oplus B_3)(A_2B_2+(A_2\oplus B_2)(A_1B_1+(A_1\oplus B_1)A_0B_0)) \\ P & = (A_3\oplus B_3)(A_2\oplus B_2)(A_1\oplus B_1)(A_0\oplus B_0) \end{aligned}
GP=A3B3+(A3⊕B3)(A2B2+(A2⊕B2)(A1B1+(A1⊕B1)A0B0))=(A3⊕B3)(A2⊕B2)(A1⊕B1)(A0⊕B0)
则有
C
4
=
G
+
P
C
0
C_{4}=G+PC_0
C4=G+PC0
我们称G为进位发生输出,P为进位传递输出。G的作用就是通过
A
、
B
A、B
A、B产生进位,而P的作用就是将
C
0
C_0
C0传递到
C
4
C_4
C4。增加P和G的目的就是在于实现多组ALU之间的先行进位,也称为先行进位发生器(CLA)
在实现了4位加法器之后,我们开始进行对位数进行扩展。其基本思想就是将实现好的4位加法器当作1位全加器来使用:1位全加器在设计4位中如何使用,4位加法器就在16位中如何使用
C
n
+
1
=
G
0
+
P
0
C
n
C
n
+
2
=
G
1
+
P
1
C
n
+
x
C
n
+
3
=
G
2
+
P
2
C
n
+
y
C
n
+
4
=
G
3
+
P
3
C
n
+
z
片
内
并
行
进
位
,
片
间
串
行
进
位
C_{n+1} = G_0+P_0C_n \quad \quad C_{n+2} = G_1+P_1C_{n+x} \\ C_{n+3} = G_2+P_2C_{n+y} \quad \quad C_{n+4} = G_3+P_3C_{n+z} \\ 片内并行进位,片间串行进位
Cn+1=G0+P0CnCn+2=G1+P1Cn+xCn+3=G2+P2Cn+yCn+4=G3+P3Cn+z片内并行进位,片间串行进位
我们也可以将片间设计为先行进位
2.5.3 定点运算器的基本结构
-
单总线
在同一时间内,只能有一个操作数放在单总线上。把两个操作数输入到ALU需要分两次,先放入A,再放入B,最后计算出结果后再经总线放入目标寄存器。完成ALU计算任务需要三次串行选通操作。
-
双总线
两个数同时放入ALU,只需要一次操作即可。
ALU计算完成时,输出不能直接送入总线上,因为当形成操作结果的输出时,两条总线都被输入数据占据,因此,必须要在ALU输出端加缓冲器。完成ALU计算任务只需要两步串行选通操作。
-
三总线
ALU的两个输入端分别由两个总线供给,输出端与第三条总线相连。因此,算术逻辑操作只需要一步即可完成任务。
2.6 浮点运算与浮点运算器(重点)
2.6.1 浮点表示法
浮点的意思就是小数点的位置会浮动,是不是很神奇。正因为如此,在相同的位数下,浮点数能够存储的数据范围比定点数多得多。
格式为:
N
=
R
E
⋅
M
N=R^E·M
N=RE⋅M
其中R为底数(默认取2),E为指数,M为尾数。
就好比十进制的科学计数法 N = 1 0 E ⋅ M N = 10^E·M N=10E⋅M。E位数越大,能够表示的范围就越大;M位数越大,表示的精度就越高。
2.6.2 IEEE754标准
同一个浮点数由于阶码和尾数的不同会有多种的表现形式。在IEEE754标准中,规定了浮点数的表示格式和运算规则
-
底数为2且固定
-
32位浮点数
- S:数的符号位,占1位,0表负数,1表整数
- E:阶码,占8位,移码表示
- M:尾数,占32位,原码纯小数表示
- 规格化
- 尾数:绝对值必须大于等于1/2,也就是最左位(最高有效位)总是1,故这一位可以不予存储,而认为隐藏在小数点的左边,取出M时自动补上1。
- 阶码:将浮点数的指数真值e变成阶码E时,应将指数e加上一个固定的偏移值127(01111111),即E=e+127
题目可能会给出IEEE754标准的十六进制形式,让你计算十进制的数值。①将十六进制转换为二进制,判断字长是32位还是64位②按照浮点数的格式,计算阶符、阶码和尾数③套公式计算数值(M保存时省略了最前面的1,所以在计算时应该加上)
例:
-
原码尾数的规格化形式
- 正数:0.1XXXXXX
- 负数:1.1XXXXXX
-
补码尾数的规格化形式
- 正数:0.1XXXXXX
- 负数:1.0XXXXXX
一个规格化后的32位浮点数x的真值为:
x
=
(
−
1
)
s
×
(
1.
M
)
×
2
e
,
e
=
E
−
127
x = (-1)^s×(1.M)×2^e,e=E-127
x=(−1)s×(1.M)×2e,e=E−127
这里举一个浮点数规格化的例子
- 小数点向左移说明数值在变小,为了保持原大小,指数需要变大
- 小数点向右移说明数值在变大,为了保持原大小,指数需要变小
2.6.3 浮点加减法运算
浮点加减法运算的过程为:
-
比较阶码大小并完成对阶(向大阶对齐)
阶码小的数向阶码大的数对齐
对阶过程中小阶每加一,尾数就右移一位
-
尾数进行加减运算
-
结果规格化
-
向左规格化
在尾数运算时,其求和结果可能为00.0XXX或者11.1XXX,这时操作结果的绝对值小于0.5,我们应该将其左移增大绝对值。
所以我们要将00.0XXX→00.1XXX或11.1XXX→11.0XXX
-
向右规格化
当双符号位结果溢出时,也就是出现
01.XXXX或10.XXXX,这时操作结果的绝对值大于1,所以我们应该右移缩小绝对值,同时阶码加一
-
-
舍入处理
0舍1入
-
溢出处理
规格化后阶码小于机器码所能表示的最小数值,叫浮点数的下溢;反之称之为上溢,需要做溢出中断处理
例: