3.1 加减运算
主要是带符号整数和无符号整数的区别,补码加减运算公式:
[
A
+
B
]
补
=
[
A
]
补
+
[
B
]
补
(
m
o
d
2
n
)
[
A
−
B
]
补
=
[
A
]
补
+
[
−
B
]
补
(
m
o
d
2
n
)
[A+B]_补=[A]_补+[B]_补 (mod\ 2^n)\\ [A-B]_补=[A]_补+[-B]_补(mod\ 2^n)
[A+B]补=[A]补+[B]补(mod 2n)[A−B]补=[A]补+[−B]补(mod 2n)
实现减法的主要工作在于求
[
−
B
]
补
[-B]_补
[−B]补,其值为
[
B
]
补
‾
+
1
{\overline{[B]_补}}+1
[B]补+1
3.1.1 条件标志位
零标志ZF、溢出标志OF、进\借位标志CF、符号标志SF称为条件标志,计算方式如下:
- OF:若 A A A与 B B B同号但与 S u m Sum Sum不同号,则为1,否则为0
- SF:Sum的符号位
- ZF:若Sum为0,则为1,否则为0
- CF: C o u t ⊕ s u b Cout\oplus sub Cout⊕sub
3.1.2 加法运算
无符号加溢出的条件:CF=1 (即最终加出来有进位,显然溢出)
有符号加溢出的条件:OF=1(两个整数相加,加出来是个负数,显然溢出)
3.1.3 减法运算
无符号减溢出的条件:CF=1(差为负数,即借位CF=1,向最高位借了1)
有符号减溢出的条件:最高位和次高位的进位不同,或和的符号位和加数的符号位不同
做减法以比较大小,规则:
- Unsigned:CF=0时,大于
- Signed:OF=CF时,大于
3.2 乘法运算
假定: [ x ] 原 = x 0 x 1 ⋯ x n , [ y ] 原 = y 0 y 1 ⋯ y n , [x]_原=x_0x_1\cdots x_n,[y]_原=y_0y_1\cdots y_n, [x]原=x0x1⋯xn,[y]原=y0y1⋯yn,求 [ x + y ] 原 [x+y]_原 [x+y]原
数值部分 z 1 ⋯ z 2 n = ( 0. x 1 x 2 ⋯ x n ) ⋅ ( 0. y 1 y 2 ⋯ y n ) z_1\cdots z_{2n}=(0.x_1x_2\cdots x_n)\cdot (0.y_1y_2\cdots y_n) z1⋯z2n=(0.x1x2⋯xn)⋅(0.y1y2⋯yn)
(小数点位置约定,不区分小数还是整数)
手工运算就是列竖式,整个过程用到两种操作:加法和左移,可用ALU和移位器来实现乘法运算。
公式推导
x
⋅
y
=
x
⋅
(
0.
y
1
y
2
⋯
y
n
)
=
x
y
1
⋅
2
−
1
+
x
y
2
⋅
2
−
2
+
⋯
+
x
y
n
−
1
⋅
2
−
(
n
−
1
)
+
x
y
n
⋅
2
−
n
=
2
−
1
(
2
−
1
(
2
−
1
⋯
2
−
1
(
2
−
1
⏟
n
个
2
−
1
(
0
+
x
y
n
)
+
x
y
n
−
1
)
+
⋯
+
x
y
2
)
+
x
y
1
)
\begin{align*} x\cdot y&= x \cdot(0.y_1 y_2 \cdots y_n)&\\ &=xy_1 \cdot 2^{-1}+xy_2 \cdot 2^{-2}+\cdots+xy_{n-1}\cdot 2^{-(n-1)}+xy_n\cdot2^{-n}\\ &=\underbrace{ 2^{-1}(2^{-1}(2^{-1}\cdots 2^{-1}(2^{-1}}_{n个2^{-1}}{(0+xy_n)+xy_{n-1})+\cdots+xy_2)+xy_1)}\\ \end{align*}
x⋅y=x⋅(0.y1y2⋯yn)=xy1⋅2−1+xy2⋅2−2+⋯+xyn−1⋅2−(n−1)+xyn⋅2−n=n个2−1
2−1(2−1(2−1⋯2−1(2−1(0+xyn)+xyn−1)+⋯+xy2)+xy1)
显然具有递归的性质,因此无符号乘法过程课归纳为下列算式:设
P
0
=
0
P_0=0
P0=0
P
1
=
2
−
1
(
P
0
+
x
y
n
)
P
2
=
2
−
1
(
P
1
+
x
y
n
−
1
)
⋯
⋯
P
n
=
2
−
1
(
P
n
−
1
+
x
y
1
)
\begin{align*} &P_1 =2^{-1}(P_0+xy_n)\\ &P_2 =2^{-1}(P_1+xy_{n-1})\\ &\ \ \ \ \ \cdots \ \cdots \\ &P_n=2^{-1}(P_{n-1}+xy_1) \end{align*}
P1=2−1(P0+xyn)P2=2−1(P1+xyn−1) ⋯ ⋯Pn=2−1(Pn−1+xy1)
其递推公式为:
P
i
+
1
=
2
−
1
(
P
i
+
x
y
n
−
i
)
P_{i+1}=2^{-1}(P_i+xy_{n-i})
Pi+1=2−1(Pi+xyn−i),最终乘积
P
n
=
x
y
P_n=xy
Pn=xy
以上为手工计算的特点,再计算机内部做以下改进:
- 每次得到 x y i xy_i xyi后,与前面所得的结果累加,得到 P i P_i Pi,称为部分积。减少保存各次相乘结果的开销
- 每次得到 x y i xy_i xyi后,不将它左移与前次部分积 P i P_i Pi相加,而将部分积 P i P_i Pi右移后再与 x y i xy_i xyi相加。因为加法运算始终对部分积中高 n n n位进行,故用 n n n位加法器可实现两个 n n n位数相乘
- 对乘数中为“1”的位执行加法和右移,对为“0”的位只执行右移,而不执行加法。
- 被乘数寄存器X:存放被乘数
- 乘积寄存器P:开始置初始部分积 P 0 = 0 P_0=0 P0=0;结束时,存放的是64位乘积的高32位
- 乘数寄存器Y:开始时置乘数;结束时,存放的是64位乘积的低32位
- 进位触发器C:保存加法器的进位信号
- 循环次数计数器Cn:存放循环次数。初值位32,没循环一次,就-1,为0时结束
- ALU:乘法核心部件,在逻辑控制下,对P和X的内容加,在写使能控制下运算结果被送回P,进位在C中
3.2.2 原码两位乘法
每次取乘数两位判断,只需 n 2 \frac{n}{2} 2n次循环,快一倍
递推公式
00: P i + 1 = 2 − 2 P i P_{i+1}=2^{-2}P_i Pi+1=2−2Pi
01: P i + 1 = 2 − 2 ( P i + X ) P_{i+1}=2^{-2}(P_i+X) Pi+1=2−2(Pi+X)
10: P i + 1 = 2 − 2 ( P i + 2 X ) P_{i+1}=2^{-2}(P_i+2X) Pi+1=2−2(Pi+2X)
11: P i + 1 = 2 − 2 ( P i + 3 X ) = 2 − 2 ( P i + 4 X − X ) = 2 − 2 ( P i − X ) + X P_{i+1}=2^{-2}(P_i+3X)=2^{-2}(P_i+4X-X)=2^{-2}(P_i-X)+X Pi+1=2−2(Pi+3X)=2−2(Pi+4X−X)=2−2(Pi−X)+X
y i − 1 y_{i-1} yi−1 y i y_i yi T T T | 操作 | 迭代公式 |
---|---|---|
0 0 0 | 0 → T 0\rightarrow T 0→T | 2 − 2 ( P i ) 2^{-2}(P_i) 2−2(Pi) |
0 0 1 | +X 0 → T 0\rightarrow T 0→T | 2 − 2 ( P i + X ) 2^{-2}(P_i+X) 2−2(Pi+X) |
0 1 0 | +X 0 → T 0\rightarrow T 0→T | 2 − 2 ( P i + X ) 2^{-2}(P_i+X) 2−2(Pi+X) |
0 1 1 | +2X 0 → T 0\rightarrow T 0→T | 2 − 2 ( P i + 2 X ) 2^{-2}(P_i+2X) 2−2(Pi+2X) |
1 0 0 | +2X 0 → T 0\rightarrow T 0→T | 2 − 2 ( P i + X ) 2^{-2}(P_i+X) 2−2(Pi+X) |
1 0 1 | -X 1 → T 1\rightarrow T 1→T | 2 − 2 ( P i − X ) 2^{-2}(P_i-X) 2−2(Pi−X) |
1 1 0 | -X 1 → T 1\rightarrow T 1→T | 2 − 2 ( P i − X ) 2^{-2}(P_i-X) 2−2(Pi−X) |
1 1 1 | 1 → T 1\rightarrow T 1→T | 2 − 2 ( P i ) 2^{-2}(P_i) 2−2(Pi) |
主要是加多少个X,T用来记录下次是否要执行“+X”,例如11 1,则需要加4X,那么直接在下一步中+X即可,所以当前一步直接右移两位。 y i − 1 y_{i-1} yi−1表示高位, y i y_i yi表示低位。
例子:
在两位乘法中,由于涉及到减法,可能导致中间结果为负数,所以符号位是重要且有意义的。
3.2.3 补码一位乘法
Booth’s Algorithm
假定 [ X ] 补 = x n − 1 x n − 2 ⋯ x 1 x 0 , [ Y ] 补 = y n − 1 y n − 2 ⋯ y 1 y 0 [X]_补=x_{n-1}x_{n-2}\cdots x_1x_0,[Y]_补=y_{n-1}y_{n-2}\cdots y_1y_0 [X]补=xn−1xn−2⋯x1x0,[Y]补=yn−1yn−2⋯y1y0,求 [ X × Y ] 补 [X\times Y]_补 [X×Y]补
n
=
32
n=32
n=32时,令
y
−
1
=
0
y_{-1}=0
y−1=0,有
Y
=
−
y
31
⋅
2
31
+
y
30
⋅
2
30
+
⋯
+
y
1
⋅
2
1
+
y
−
1
⋅
2
0
=
−
y
31
⋅
2
31
+
(
y
30
⋅
2
31
−
y
30
⋅
2
30
)
+
⋯
+
(
y
0
⋅
2
1
−
y
0
⋅
2
0
)
+
y
−
1
⋅
2
0
=
(
y
30
−
y
31
)
⋅
2
31
+
(
y
29
−
y
30
)
⋅
2
30
+
⋯
+
(
y
0
−
y
1
)
⋅
2
1
+
(
y
−
1
−
y
0
)
⋅
2
0
2
−
32
[
X
×
Y
]
补
=
(
y
30
−
y
31
)
X
⋅
2
−
1
+
(
y
29
−
y
30
)
X
⋅
2
−
2
+
⋯
+
(
y
−
1
−
y
0
)
X
⋅
2
−
32
=
2
−
1
(
2
−
1
⋯
(
2
−
1
(
2
−
1
(
y
−
1
−
y
0
)
X
)
+
(
y
0
−
y
1
)
X
)
+
⋯
+
(
y
30
−
y
31
)
X
)
\begin{align} Y&=-y_{31}\cdot2^{31}+y_{30}\cdot2^{30}+\cdots+y_1\cdot2^{1}+y_{-1}\cdot2^{0}\\ &=-y_{31}\cdot2^{31}+(y_{30}\cdot2^{31}-y_{30}\cdot2^{30})+\cdots+(y_0\cdot2^{1}-y_0\cdot2^{0})+y_{-1}\cdot2^{0}\\ &=(y_{30}-y_{31})\cdot2^{31}+(y_{29}-y_{30})\cdot2^{30}+\cdots+(y_0-y_1)\cdot2^{1}+(y_{-1}-y_0)\cdot2^{0}\\ 2^{-32}[X\times Y]_补&=(y_{30}-y_{31})X\cdot2^{-1}+(y_{29}-y_{30})X\cdot2^{-2}+\cdots+(y_{-1}-y_0)X\cdot2^{-32}\\ &=2^{-1}(2^{-1}\cdots(2^{-1}(2^{-1}(y_{-1}-y_0)X)+(y_0-y_1)X)+\cdots+(y_{30}-y_{31})X) \end{align}
Y2−32[X×Y]补=−y31⋅231+y30⋅230+⋯+y1⋅21+y−1⋅20=−y31⋅231+(y30⋅231−y30⋅230)+⋯+(y0⋅21−y0⋅20)+y−1⋅20=(y30−y31)⋅231+(y29−y30)⋅230+⋯+(y0−y1)⋅21+(y−1−y0)⋅20=(y30−y31)X⋅2−1+(y29−y30)X⋅2−2+⋯+(y−1−y0)X⋅2−32=2−1(2−1⋯(2−1(2−1(y−1−y0)X)+(y0−y1)X)+⋯+(y30−y31)X)
得出部分积公式:
P
i
=
2
−
1
(
P
i
−
1
+
(
y
i
−
1
−
y
i
)
X
)
P_i=2^{-1}(P_{i-1}+(y_{i-1}-y_i)X)
Pi=2−1(Pi−1+(yi−1−yi)X),(记住低位减高位就行,且
y
−
1
=
0
y_{-1}=0
y−1=0)
当前位 | 右边位 | 操作 |
---|---|---|
1 | 0 | 减被乘数 |
1 | 1 | 加0(不操作) |
0 | 1 | 加被乘数 |
0 | 0 | 加0(不操作) |
都右移一位。
3.2.3 补码两位乘法
溢出判断:
- 无符号:若高n位全0,则不溢出。
- 有符号:若高n位全0或全1且等于低n位得最高位,不溢出。
3.3 除法运算
手算除法要点:
- 被除数与除数相减,够减则上商为1,否则上商为0
- 每次得到得差为中间余数,将除数右移后与上次的中间余数比较,用中间余数减除数,够减则上商为1,否则为0
- 重复执行第2步,直到求得的商的位数足够为止。
除前预处理:
- 若被除数=0,且除数≠0,或定点整数除法时 ∣ 被除数 ∣ < ∣ 除数 ∣ |被除数|<|除数| ∣被除数∣<∣除数∣,则商为0,不再继续
- 若被除数≠0、除数=0,则发出“除数为0”的异常
- 若被除数和除数都为0,发出"NaN"
两个 n n n位数相除的情况:
- 定点正整数(即无符号数)相除:在被除数的高位添n个0
- 定点正小数(即原码小数)相除:在被除数的低位添加n个0
如此,可将所有情况统一为:一个2n位数除以一个n位数
第一次试商为1,说明商有n+1位数,溢出。
若浮点数中尾数原码小数运算,第一次试商为1,则说明位数部分有“溢出”,可通过浮点数的“右移”消除“溢出”。所以在浮点数运算器中,第一次得到的商“1”要保留。
例: 0.11110000 / 0.1000 = + 1.1110 0.11110000/0.1000=+1.1110 0.11110000/0.1000=+1.1110
3.3.1 无符号除法
- 除数寄存器Y:存放除数
- 余数寄存器R:初始时为低32位被除数;结束时是32位商
- 余数/商寄存器Q:初始时为低32位被除数;结束时是32位商
- 循环次数计数器Cn:存放循环次数。
- ALU:除法核心部件,在逻辑控制下,对R和Y的内容进行加减,在写使能控制下运算结果被送回寄存器R
恢复余数法:
每次都减,小于0,则上0,加回除数后再左移,大于0则上1,直接左移
加减交替法:
根据恢复余数法(设B为除数,Ri为第i次中间余数),有
若 R i < 0 R_i<0 Ri<0,则商上“0”,并做加法恢复余数,即 R i + 1 = 2 ( R i + 2 n ∣ B ∣ ) − 2 n ∣ B ∣ = 2 R i + 2 n ∣ B ∣ R_{i+1}=2(R_i+2^n|B|)-2^n|B|=2R_i+2^n|B| Ri+1=2(Ri+2n∣B∣)−2n∣B∣=2Ri+2n∣B∣,(负,0,+)
若 R i > = 0 R_i>=0 Ri>=0,则商上“1”,不需要恢复余数,即 R i + 1 = 2 R i − 2 n ∣ B ∣ R_{i+1}=2R_i-2^n|B| Ri+1=2Ri−2n∣B∣,(正,1,-)
注意:最后一次上商为0的话,需要"纠余"处理,即把试商时被减掉的除数加回去,恢复真正的余数。
3.3.2 有符号除法
3.4 浮点数运算
设两个规格化浮点数分别为 A = M a 2 E a , B = M b 2 E b A= M_a2^{E_a},B=M_b2^{E_b} A=Ma2Ea,B=Mb2Eb,则:
A ± B = ( M a ± M b ⋅ 2 − ( E a − E b ) ⋅ 2 E a ) A\pm B=(M_a\pm M_b\cdot2^{-(E_a-E_b)}\cdot2^{E_a}) A±B=(Ma±Mb⋅2−(Ea−Eb)⋅2Ea),假设 E a > = E b E_a>=E_b Ea>=Eb
A ∗ B = ( M a × M b ) ⋅ 2 E a + E b A*B=(M_a\times M_b)\cdot2^{E_a+E_b} A∗B=(Ma×Mb)⋅2Ea+Eb
A / B = ( M a / M b ) ⋅ 2 E a − E b A/B =(M_a/M_b)\cdot2^{E_a-E_b} A/B=(Ma/Mb)⋅2Ea−Eb
上述运算结果可能出现以下几种情况
阶码上溢:一个正指数超过了最大允许值($+\infty/-\infty $溢出)
阶码下溢:一个负指数超过了最大允许值(+0/-0)
尾数溢出:最高有效位有进位(可右规处理,结果不一定溢出)
非规格化尾数:数值部分高位为0(左规)
右规或对阶时,右段有效位丢失(尾数舍入,运算过程中添加保护位)
3.4.1 对阶
- 小阶向大阶看齐,阶小的那个数的尾数右移,右移位数等于两个阶码差的绝对值
- IEEE 754尾数右移时,要将隐含的“1”移到小数部分,高位补0,移出的低位保留到特定的“附加位”上
可通过计算 [ E ] 补 = [ E x − E y ] 补 = [ E x ] 移 + [ − [ E y ] 移 ] 补 ( m o d 2 n ) [E]_补=[E_x-E_y]补=[E_x]_移+[-[E_y]_移]_补(mod\ 2^n) [E]补=[Ex−Ey]补=[Ex]移+[−[Ey]移]补(mod 2n)来判断两数的阶差
附加位
IEEE754规定:中间结果必须在右边加2个附加位(guard & round)
- Guard bit(保护位):在significand右边的位
- Rounding bit(舍入位):在保护位右边的位