[ X ] 补 + [ X ] 补 = [ X + Y ] 补 m o d 2 n + 1 [X]_补 + [X]_补 = [X + Y]_补\ mod\ 2^{n + 1} [X]补+[X]补=[X+Y]补 mod 2n+1
算法理解
例1 已知 X = + 10010 X = + 10010 X=+10010 Y = − 10101 Y = - 10101 Y=−10101 求 X + Y X + Y X+Y
解: [ X ] 补 = 0 10010 [X]_补 = 0\ 10010 [X]补=0 10010 [ Y ] 补 = 1 01011 \ \ [Y]_补 = 1\ 01011 [Y]补=1 01011
[ X + Y ] 补 = [ X ] 补 + [ Y ] 补 = 0 10010 + 1 01011 = 1 11101 [X + Y]_补 = [X]_补 + [Y]_补 = 0\ 10010 + 1\ 01011 = 1\ 11101 [X+Y]补=[X]补+[Y]补=0 10010+1 01011=1 11101
所以: X + Y = − 00011 X + Y = - 00011 X+Y=−00011
[ X − Y ] 补 = [ X ] 补 − [ Y ] 补 = [ X ] 补 + [ − Y ] 补 [X - Y]_补 = [X]_补 - [Y]_补 = [X]_补 + [-Y]_补 [X−Y]补=[X]补−[Y]补=[X]补+[−Y]补
算法理解
例2 已知 [ Y ] 补 = 1 0011 [Y]_补 = 1\ 0011 [Y]补=1 0011 求 [ − Y ] 补 [-Y]_补 [−Y]补
解: [ Y ] 补 = 1 0011 [Y]_补 = 1\ 0011 [Y]补=1 0011
∴ Y = − 1101 − Y = 1101 \therefore\ Y = - 1101 \ \ \ \ \ -Y = 1101 ∴ Y=−1101 −Y=1101
∴ [ − Y ] 补 = 0 1101 \therefore\ [-Y]_补 = 0\ 1101 ∴ [−Y]补=0 1101
对比 [ Y ] 补 = 1 0011 [Y]_补 = 1\ 0011 [Y]补=1 0011,可知:
通过右向扫描 [ Y ] 补 [Y]_补 [Y]补,在遇到数字 1 及之前,直接输出遇到的数字,遇到 1 之后,取反输出,即可得到 [ − Y ] 补 [-Y]_补 [−Y]补,反之亦然!
例3 已知 X = + 10101 X = + 10101 X=+10101 Y = + 10010 Y = + 10010 Y=+10010 求 X − Y X - Y X−Y
解: [ X ] 补 = 0 10101 [X]_补 = 0\ 10101 [X]补=0 10101, [ Y ] 补 = 0 10010 [Y]_补 = 0\ 10010 [Y]补=0 10010, [ − Y ] 补 = 1 01110 [-Y]_补 = 1\ 01110 [−Y]补=1 01110
[ X + Y ] 补 = [ X ] 补 + [ − Y ] 补 = 0 10101 + 1 01110 = 1 0 00011 [X + Y]_补 = [X]_补 + [-Y]_补 = 0\ 10101 + 1\ 01110 = 1\ 0\ 00011 [X+Y]补=[X]补+[−Y]补=0 10101+1 01110=1 0 00011
所以 X − Y = + 00011 X - Y = +00011 X−Y=+00011
运算结果超过了某种数据类型的表示范围。
例4 已知 X = + 10010 X = + 10010 X=+10010 Y = + 10101 Y = + 10101 Y=+10101 求 X + Y X + Y X+Y
解: [ X ] 补 = 0 10010 [X]_补 = 0\ 10010 [X]补=0 10010 Y = 0 10101 Y = 0\ 10101 Y=0 10101
[ X + Y ] 补 = [ X ] 补 + [ Y ] 补 = 0 10010 + 0 10101 = 1 00111 [X + Y]_补 = [X]_补 + [Y]_补 = 0\ 10010 + 0\ 10101 = 1\ 00111 [X+Y]补=[X]补+[Y]补=0 10010+0 10101=1 00111
所以: X + Y = − 11001 X + Y = -11001 X+Y=−11001
两个正数之和为负数!
例5 已知 X = − 10010 X = - 10010 X=−10010 Y = − 10101 Y = - 10101 Y=−10101 求 X + Y X + Y X+Y
解: [ X ] 补 = 1 01110 [X]_补 = 1\ 01110 [X]补=1 01110 [ Y ] 补 = 1 01011 [Y]_补 = 1\ 01011 [Y]补=1 01011
[ X + Y ] 补 = [ X ] 补 + [ Y ] 补 = 1 01110 + 1 01011 = [X + Y]_补 = [X]_补 + [Y]_补 = 1\ 01110 + 1\ 01011 = [X+Y]补=[X]补+[Y]补=1 01110+1 01011= 1 1 1 0 11001 0\ 11001 0 11001
所以: X + Y = + 11001 X + Y = + 11001 X+Y=+11001
两个负数之和为正数!
溢出只可能发生在同符号数相加时,包括 [ X ] 补 [X]_补 [X]补 [ Y ] 补 [Y]_补 [Y]补; [ X ] 补 [X]_补 [X]补 与 [ − Y ] [-Y] [−Y] 同号;
(1)方法1:对操作数和运算结果的符号位进行检测
当结果的符号位与操作数的符号不相同时就表明发生了溢出(设 X 0 X_0 X0 Y 0 Y_0 Y0 为参加运算数的符号位, S 0 S_0 S0 为结果的符号位)
V = X 0 Y 0 S 0 ‾ + X 0 ‾ Y 0 ‾ S 0 V = X_0\ Y_0\ \overline{S_0} + \overline{X_0}\ \overline{Y_0}\ S_0 V=X0 Y0 S0+X0 Y0 S0
当 V = 1 V = 1 V=1 时,运算结果溢出,根据该逻辑表达式,容易画出相应电路。
(2)方法2:对最高数据位进位和符号进位进行检测
设运算时最高数据位产生的进位为 C 1 C_1 C1,符号位产生的进位为 C 0 C_0 C0,溢出检测电路为: V = C 0 ⨁ C 1 V = C_0 \bigoplus C_1 V=C0⨁C1
0. X 1 + 0. Y 1 0.X_1 + 0.Y_1 0.X1+0.Y1 此时: C 0 = 0 C_0 = 0 C0=0,若 C 1 = 1 C_1 = 1 C1=1 则改变了结果符号位,发生溢出。
1. X 1 + 1. Y 1 1.X_1 + 1.Y_1 1.X1+1.Y1 此时: C 0 = 1 C_0 = 1 C0=1,若 C 1 = 0 C_1 = 0 C1=0 则改变了结果符号位,发生溢出。
(3)方法3:用变型补码
[ X ] 补 = X f 1 X f 2 . X 1 X 2 X 3 … X n m o d 2 n + 2 [X]_补 = X_{f1}X_{f2}\ .\ X_1X_2X_3\ldots X_n mod \ 2^{n + 2} [X]补=Xf1Xf2 . X1X2X3…Xnmod 2n+2
溢出的判断: V = X f 1 ⨁ X f 2 V = X_{f1}\bigoplus X_{f2} V=Xf1⨁Xf2
例6 已知 X = − 10010 X = - 10010 X=−10010 Y = − 10101 Y = - 10101 Y=−10101 求 X + Y X + Y X+Y
解: [ X ] 补 = 11 01110 [X]_补 = 11\ 01110 [X]补=11 01110 [ Y ] 补 = 11 01011 [Y]_补 = 11\ 01011 [Y]补=11 01011
[ X + Y ] 补 = [ X ] 补 + [ Y ] 补 = 11 01110 + 11 01011 = [X + Y]_补 = [X]_补 + [Y]_补 = 11\ 01110 + 11\ 01011 = [X+Y]补=[X]补+[Y]补=11 01110+11 01011= 1 1 1 10 10 10 11001 11001 11001
V = 1 ⨁ 0 = 1 V = 1 \bigoplus 0 = 1 V=1⨁0=1 故发生溢出!
上述三种方法可基于逻辑表达式画出相应电路,在后面的运算器部分,还将具体讲解。
(4)溢出判断的软件方法
int tadd_ok(int x, int y)
{
int sum = x + y;
int neg_over = x < 0 && y < 0 && sum >= 0;
int pos_over = x >= 0 && y >= 0 && sum < 0;
return !neg_over && !pos_over;
}
体会软/硬件功能的等效性和差异性!
体会软/硬件协同的系统观!
1、无符号数加法的溢出可用 ALU 的进位表示;
2、无符号数减法的溢出也可用带加/减功能的 ALU 的进位取反后表示。