第30题

第 3 版 · OCR 辅助 · 原书检索 · 文字用于定位,公式与图表请回原页核验 · 本次导入快照

## 第30题

$x$ 和 $y$ 的机器数分别表示为 $x = 40\mathrm{E}80000\mathrm{H} = 010000001\dots ,y = \mathrm{C}2040000\mathrm{H} = 110000100\dots$,因此,$\left[E_{x}\right]_{\text{移}} = 10000001,\left[E_{y}\right]_{\text{移}} = 10000100,\left[\Delta E\right]_{\text{补}} = \left[E_{x} - E_{y}\right]_{\text{补}} = \left[E_{x}\right]_{\text{移}} + \left[-\left[E_{y}\right]_{\text{移}}\right]_{\text{补}} = 10000001 + 01111100 = 11111101$。

## 第31题

对于IEEE 754单精度浮点数加减运算,若对阶时得到的两个阶码之差的绝对值 $|\Delta E| = 24$,则说明阶小的那个数的尾数右移24位,进行尾数加减运算时,虽然其结果的前24位直接取阶大的那个数的相应位,但是,由于可以保留附加位,阶小的那个数右移后的尾数可能会在舍入时向前面一位进1。例如, $1.00\dots 01\times 2^{1} + 1.10\dots 00\times 2^{-23} = 1.00\dots 01\times 2^{1} + 0.00\dots 0011\times 2^{1} = 1.00\dots 0111\times 2^{1}$。其中,加粗的两位为保留的附加位,最终需要根据这两位进行舍入,显然,舍入后的结果为 $1.00\dots 10\times 2^{1}$,并不等于阶大的那个数。若 $|\Delta E| = 25$,则保留的附加位中,最左边第1位一定是0,采用就近舍入时,这些附加位完全被丢弃。因此,$|\Delta E| \geqslant 25$ 时,可以使运算结果直接取阶大的那个数。

## 3.6 分析应用题

1. 考虑下列 C 语言程序代码:

int i = 65535;
short si = (short) i;
int j = si;
假定上述程序段在某32位机器上执行,sizeof(int) = 4,则变量 $i$、si 和 $j$ 的值分别是多少?为什么? ### 【分析解答】 在一台32位机器上执行上述代码段时,$i$ 为32位补码表示的定点整数,第2行要求强行将一个32位带符号数截断为16位带符号整数,65535的32位补码表示为0000FFFFH,截断为16位后变成FFFFH,它是-1的16位补码表示,因此si的值是-1。再将该16位带符号整数扩展为32位时,就变成了FFFFFFFFH,它是-1的32位补码表示,因此 $j$ 的值也为-1。也就是说,$i$ 的值原来为65535,经过截断、再扩展后,其值变成了-1。 2. 考虑以下C语言程序代码:
int func1(unsigned word)
{
return(int)((word << 24) >> 24);
}

int func2(unsigned word)
{


<!-- page: 64 -->

```txt
return((int)word << 24) >> 24;
假设在一个 32 位机器上执行这些函数,sizeof(int) = 4。说明函数 func1 和 func2 的功能,并填写表 3.1,给出对表中“异常”数据的说明。 表 3.1 题 2 用表 [tbl-13.md](tbl-13.md) ## 【分析解答】 函数 func1 的功能是把无符号数高 24 位清零(左移 24 位再逻辑右移 24 位),结果一定是正的带符号整数;而函数 func2 的功能是把无符号数的高 24 位都变成和第 25 位一样,因为左移 24 位后左边第一位变为原来的第 25 位,然后进行算术右移,高位补符号,即高 24 位都变成和原来第 25 位相同。 根据程序执行的结果填表如表 3.2 所示,表中机器数用十六进制表示。 表 3.2 题 2 中填入结果后的表 [tbl-14.md](tbl-14.md) 因为逻辑左移和算术左移的结果完全相同,所以,函数 func1 和 func2 中第一步左移 24 位得到的结果完全相同,所不同的是右移 24 位后的结果不同。 表 3.2 中,加粗数据是一些“异常”结果。当 $w = 128$ 和 255 时,第 25 位正好是 1,因此函数 func2 执行的结果为一个负数,出现了“异常”。当 $w = 256$ 时,低 8 位为 00H,高 24 位为非 0 值,左移 24 位后使得有效数字被移出,因而发生了“溢出”,使得出现了“异常”结果 0。 3. 以下是两段 C 语言代码,函数 arith() 是直接用 C 语言写的,而 optarith() 是对 arith() 函数以某个确定的 $M$ 和 $N$ 编译生成的机器代码反编译生成的。根据 optarith(),可以推断函数 arith() 中 $M$ 和 $N$ 的值各是多少?
#define M
#define N
int arith(int x, int y)


<!-- page: 65 -->

```c
{
int result = 0;
result = x * M + y / N;
return result;
}

int optarith(int x, int y)
{
int t = x;
x <<= 4;
x -= t;
if (y < 0) y += 3;
y >>= 2;
return x + y;
}
## 【分析解答】 对反编译结果进行分析可知,对于 $x$,指令机器代码中有一条“$x$ 左移 4 位”指令,即 $x = 16x$,然后有一条“减法”指令,即 $x = 16x - x = 15x$,根据源程序知 $M = 15$;对于 $y$,有一条“$y$ 右移 2 位”指令,即 $y = y/4$,根据源程序知 $N = 4$。但是,当 $y &lt; 0$ 时,对于有些 $y$,执行 $y &gt;&gt; 2$ 后的值并不等于 $y/4$。例如,当 $y = -1$ 时,在反编译函数 optarith 中执行 $y &gt;&gt; 2$ 时,因为 $-1$ 的机器数为全 1,左移两位后还是全 1,即 $-1 &gt;&gt; 2 = -1$,结果为 $-1$;而原函数 arith 中执行 $y/4$ 时,因为 $-1/4 = 0$,得到结果为 0。 对于带符号整数来说,采用算术右移时,高位补符号,低位移出。因此,当符号位为 0 时,与无符号整数相同,采用移位方式和直接相除得到的商完全一样。当符号位为 1 时,若低位移出的是非全 0,则说明不能整除。例如,对于 $-3/2$,假定补码位数为 4,则进行算术右移操作 $1101 &gt;&gt; 1 = 1110.1\mathrm{B}$(小数点后面部分移出)后得到的商为 $-2$,而精确商是 $-1.5$,即整数商应为 $-1$。显然,算术右移后得到的商比精确商少了 $0.5$,相当于朝 $-\infty$ 方向进行了舍入,而不是朝零方向舍入。因此,这种情况下,移位得到的商与直接相除得到的商不一样,需要进行校正。 校正的方法是:对于带符号整数 $x$,若 $x &lt; 0$,则在右移前,先将 $x$ 加上偏移量 $(2^x - 1)$,然后再右移 $k$ 位。例如,上述函数 optarith 中,在执行 $y &gt;&gt; 2$ 之前加了一条语句“if $(y &lt; 0) y + 3$;”,以对 $y$ 进行校正。 4. 设 $A_4 \sim A_1$ 和 $B_1 \sim B_1$ 分别是 4 位加法器的两组输入,$C_0$ 为低位来的进位。当加法器分别采用串行进位和先行进位时,写出 4 个进位 $C_1 \sim C_1$ 的逻辑表达式。 ## 【分析解答】 串行进位:$C_1 = A_1 C_0 + B_1 C_0 + A_1 B_1$ $$ C_2 = A_2 C_1 + B_2 C_1 + A_2 B_2 $$ $$ C_3 = A_3 C_2 + B_3 C_2 + A_3 B_3 $$ $$ C_4 = A_4 C_3 + B_4 C_3 + A_4 B_4 $$ 并行进位:$C_1 = A_1 B_1 + (A_1 + B_1) C_0$ $$ C_2 = A_2 B_2 + (A_2 + B_2) A_1 B_1 + (A_2 + B_2) (A_1 + B_1) C_0 $$ $$ C_3 = A_3 B_3 + (A_3 + B_3) A_2 B_2 + (A_3 + B_3) (A_2 + B_2) A_1 B_1 + (A_3 + B_3) (A_2 $$ <!-- page: 66 --> $$ \begin{array}{l} + B _ {2}) \left(A _ {1} + B _ {1}\right) C _ {0} \\ C _ {4} = A _ {4} B _ {4} + \left(A _ {4} + B _ {1}\right) A _ {3} B _ {3} + \left(A _ {4} + B _ {4}\right) \left(A _ {3} + B _ {3}\right) A _ {2} B _ {2} + \left(A _ {4} + B _ {4}\right) \left(A _ {3} \right. \\ \left. + B _ {3}\right) \left(A _ {2} + B _ {2}\right) A _ {1} B _ {1} + \left(A _ {1} + B _ {4}\right) \left(A _ {3} + B _ {3}\right) \left(A _ {2} + B _ {2}\right) \left(A _ {1} + B _ {1}\right) C _ {0} \\ \end{array} $$ 5. 某字长为 8 位的计算机中, $x$ 和 $y$ 为无符号整数,已知 $x = 68, y = 80, x$ 和 $y$ 分别存放在寄存器 A 和 B 中。请回答下列问题(要求最终用十六进制表示二进制序列)。 (1) 寄存器 A 和 B 中的内容分别是什么? (2) 若 $x$ 和 $y$ 相加后的结果存放在寄存器 C 中,则寄存器 C 中的内容是什么?运算结果是否正确?加法器最高位的进位 Cout 是什么?零标志 ZF 和进位标志 CF 各是什么? (3) 若 $x$ 和 $y$ 相减后的结果存放在寄存器 D 中,则寄存器 D 中的内容是什么?运算结果是否正确?加法器最高位的进位 Cout 是什么?零标志 ZF 和借位标志 CF 各是什么? (4) 无符号整数加/减运算时,加法器最高位进位 Cout 的含义是什么?它与进/借位标志 CF 的关系是什么? (5) 无符号整数一般用来表示什么信息?为什么通常不对无符号整数的运算结果判断溢出? 【分析解答】 (1) $x = 68 = 01000100\mathrm{B} = 44\mathrm{H};y = 80 = 01010000\mathrm{B} = 50\mathrm{H}$。所以,寄存器 A 和寄存器 B 中的内容分别是 $44\mathrm{H}$ 和 $50\mathrm{H}$。 (2) $x + y = 01000100 + 01010000 = (0)10010100 = 94\mathrm{H}$,所以,寄存器C中的内容为 $94\mathrm{H}$,对应的真值为148,运算结果正确。加法器最高位的进位Cout为0。因为结果不为0,所以 $\mathrm{ZF} = 0$;进位标志 $\mathrm{CF} = \mathrm{Cout} = 0$。 (3) $x - y = x + \left[-\frac{y}{9}\right]_{0} = 01000100 + 10110000 = (0)11110100 = F4H$,所以,寄存器D中的内容为F4H,对应的真值为244,运算结果不正确,这是因为相减结果为负数造成的。加法器最高位的进位Cout为0。因为结果不为0,所以 $\mathrm{ZF} = 0$;借位标志为 $\mathrm{CF} = \mathrm{Cout} \oplus 1 = 1$。 (4) 在加法器中进行无符号整数加法运算时,若加法器最高位进位 $Cout = 1$,则表示实际结果大于最大可表示数255;在加法器中进行无符号整数减法运算时,若加法器最高位进位 $Cout = 1$,则表示被减数大于减数,反之被减数小于减数。因此,在无符号数相加时,CF就等于 $Cout$,表示进位;在无符号数相减时,通常将最高进位 $Cout$ 取反来作为借位标志CF。也就是说,无符号整数相减时, $\mathrm{CF} = \overline{\mathrm{Cout}}$, $\mathrm{CF} = 1$ 表示有借位。 (5) 无符号整数一般用来表示地址(指针)信息,当两个地址相加结果大于最大地址而取低位地址时,相当于取模,即采用地址循环运算。因此,通常不需要判断其运算结果是否溢出,即不考虑溢出标志 OF。 6. 假设某字长为 8 位的计算机中,带符号整数采用补码表示,$x = -68, y = -80, x$ 和 $y$ 分别存放在寄存器 A 和寄存器 B 中。请回答下列问题(要求最终用十六进制表示二进制序列)。 (1) 寄存器 A 和寄存器 B 中的内容分别是什么? (2) 若 $x$ 和 $y$ 相加后的结果存放在寄存器 C 中,则寄存器 C 中的内容是什么?运算结果是否正确?加法器最高位的进位 Cout 是什么?溢出标志 OF、符号标志 SF 和零标志 ZF 各是什么? <!-- page: 67 --> (3) 若 $x$ 和 $y$ 相减后的结果存放在寄存器 D 中,则寄存器 D 中的内容是什么?运算结果是否正确?此时,加法器最高位的进位 Cout 是什么?溢出标志 OF、符号标志 SF 和零标志 ZF 各是什么? (4) 对于带符号整数的减法运算,能否直接根据 CF 的值对两个带符号整数的大小进行比较? 【分析解答】 (1) $[-68]_{\#} = [-1000100]_{\#} = 10111100\mathrm{B} = \mathrm{BCH}$。$[-80]_{\#} = [-1010000]_{\#} = 10110000\mathrm{B} = \mathrm{B0H}$。所以,寄存器 A 和寄存器 B 中的内容分别是 BCH 和 B0H。 (2) $[x + y]_{\#} = [x]_{\#} + [y]_{\#} = 10111100\mathrm{B} + 10110000\mathrm{B} = (1)01101100\mathrm{B} = 6\mathrm{CH}$,最高位前面的一位 1 被丢弃,因此,寄存器 C 中的内容为 6CH,对应的真值为 $+108$,结果不正确。加法器最高位向前面的进位 Cout 为 1。溢出标志位 OF 可采用以下任意一条规则判断得到。规则 1:若两个加数的符号位相同,但与结果的符号位相异,则溢出;规则 2:若最高位上的进位和次高位上的进位不同,则溢出。对于本题,通过这两个规则都判断出结果溢出,因此溢出标志 OF 为 1,说明寄存器 C 中的内容不是正确的结果。$x + y$ 的正确结果应是 $-68 + (-80) = -148$,而运算的结果为 108,两者不等。其原因是因为 $x + y$ 的值(即 $-148$)小于 8 位补码可表示的最小值(即 $-128$),即结果发生了溢出;结果的第一位(最高位)0 为符号标志位 SF,即 $\mathrm{SF} = 0$,表示结果为正数;因为结果不为 0,所以零标志 $\mathrm{ZF} = 0$。 (3) $[x - y]_{\#} = [x]_{\#} + [-y]_{\#} = 10111100\mathrm{B} + 01010000\mathrm{B} = (1)00001100\mathrm{B} = 0\mathrm{CH}$,最高位前面的一位 1 被丢弃,因此,寄存器 D 中的内容为 0CH,对应的真值为 $+12$,结果正确。加法器最高位向前面的进位 Cout 为 1。两个加数的符号位相异一定不会溢出,因此溢出标志 $\mathrm{OF} = 0$,说明寄存器 D 中的内容是真正的结果;结果的第一位(最高位)0 为符号标志位 SF,即 $\mathrm{SF} = 0$,表示结果为正数;因为结果不为 0,所以零标志 $\mathrm{ZF} = 0$。 (4) 对于带符号整数的减法运算,无法直接根据 CF 的值判断两个带符号整数的大小。例如,对于 $x = -68$,$y = 80$,$[x - y]_{\#} = [x]_{\#} + [-y]_{\#} = 10111100\mathrm{B} + 10110000\mathrm{B} = (1)01101100\mathrm{B}$,得到的 Cout 为 1,因此,$\mathrm{CF} = \mathrm{Cout} \oplus 1 = 0$,表示没有借位,推断出被减数应该大于减数,即 $-68 &gt; 80$,显然这是不正确的。因此,带符号运算中不考虑 CF 标志。 7. 某计算机标志寄存器包含 4 个标志位:CF 为进/借位标志;OF 为溢出标志;SF 为符号标志;ZF 为零标志。请说明在无符号数和带符号整数两种情况下,以下各种比较运算的逻辑判断表达式。 (1) 等于 (2) 大于 (3) 小于 (4) 大于或等于 (5) 小于或等于 【分析解答】 要比较两个数的大小,通常对这两个数先做减法,根据相减的结果生成相应的标志位,最后根据标志位判断大小。在无符号数相减时,一般不考虑 SF 和 OF 标志;在带符号整数相减时,一般不考虑 CF 标志。 假设被减数的机器数为 $X$,减数的机器数为 $Y$,则在加法器中计算两数的差时,计算公式为 $X - Y = X + (-Y)_{\#}$。以下举两个例子来说明。 假定 $X = 1001$,$Y = 1100$,则在 4 位加法器中执行以下运算:$1001 - 1100 = 1001 + 0100 = (0)1101$。若是无符号数比较,则是 9 和 12 相比,显然,$\mathrm{ZF} = 0$,$\mathrm{CF} = 1$;若是带符号整数(补码表示),则是 $-7$ 和 $-4$ 比较,显然,$\mathrm{ZF} = 0$,$\mathrm{OF} = 0$,$\mathrm{SF} = 1$。 <!-- page: 68 --> 假定 $X = 1001, Y = 0100$,则在4位加法器中执行以下运算:$1001 - 0100 = 1001 + 1100 = (1)0101$。若是无符号数比较,则是9和4相比,显然,$ZF = 0, CF = 0$;若是带符号整数,则是-7和4比较,显然,$ZF = 0, OF = 1, SF = 0$。 以下分别说明无符号数和带符号整数两种情况下各种比较运算的逻辑判断表达式。 在无符号数的情况下: (1) 等于:相减后结果为零,即 $F = ZF$。 (2) 大于:没有借位且相减后不为 0,即 $F = \overline{CF} \cdot \overline{ZF} = \overline{CF} + \overline{ZF}$。 (3) 小于:有借位且相减后不为 0,即 $F = \mathrm{CF} \cdot \overline{ZF}$。 (4) 大于或等于:没有借位或相减后结果为 0,即 $F = \overline{CF} + ZF$。 (5) 小于或等于:有借位或相减后结果为 0,即 $F = \mathrm{CF} + \mathrm{ZF}$。 在带符号整数的情况下: (1) 等于:相减后结果为零,即 $F = ZF$。 (2) 大于:相减后结果不为 0,并且,不溢出时为正,溢出时为负,即 $F = \overline{ZF} \cdot (\overline{SF} \oplus \overline{OF})$。 (3) 小于:相减后结果不为 0,并且,不溢出时为负,溢出时为正,即 $F = \overline{ZF} \cdot (\mathrm{SF} \oplus \mathrm{OF})$。 (4) 大于或等于:相减后结果为 0,或者,不溢出时为正,溢出时为负,即 $F = \mathrm{ZF} + (\mathrm{SF} \oplus \mathrm{OF})$。 (5) 小于或等于:相减后结果为 0,或者,不溢出时为负,溢出时为正,即 $F = \mathrm{ZF} + (\mathrm{SF} \oplus \mathrm{OF})$。 可以对照上述判断表达式,验证上述例子。无符号整数9和12是小于关系,相减后得到的标志 $\mathrm{ZF} = 0, \mathrm{CF} = 1$,故 $F = \mathrm{CF} \cdot \overline{\mathrm{ZF}} = 1$。无符号整数9和4是大于关系,相减后得到的标志 $\mathrm{CF} = 0, \mathrm{ZF} = 0$,故 $F = \overline{\mathrm{CF}} \cdot \overline{\mathrm{ZF}} = 1$。带符号整数-7和-4是小于关系,相减后得到的标志 $\mathrm{ZF} = 0, \mathrm{OF} = 0, \mathrm{SF} = 1$,故 $F = \overline{\mathrm{ZF}} \cdot (\mathrm{SF} \oplus \mathrm{OF}) = 1$。带符号整数-7和4是小于关系,相减后得到的标志 $\mathrm{ZF} = 0, \mathrm{OF} = 1, \mathrm{SF} = 0$,故 $F = \overline{\mathrm{ZF}} \cdot (\mathrm{SF} \oplus \mathrm{OF}) = 1$。 8. 填写表3.3,注意对比无符号数和带符号整数的乘法结果,以及截断操作前、截断操作后的结果。 表 3.3 题 8 用表 [tbl-15.md](tbl-15.md) <!-- page: 69 -->