Skip to content

2017年 408 计算机组成原理 第 44 题

计算机组成原理2017年综合题11分

题目

在按字节编址的计算机 M 上,题 43 中 f1 的部分源程序(阴影部分)与对应的机器级代码(包括指令的虚拟地址)如下图所示。

int f1(unsigned n)
1   00401020 55         push ebp
...      ...        ...
    for (unsigned i = 0; i <= n-1; i++) {
...      ...        ...
20  0040105E 39 4D F4   cmp dword ptr [ebp-0Ch],ecx
...      ...        ...
        power *= 2;
...      ...        ...
23  00401066 D1 E2      shl edx,1
...      ...        ...
    return sum;
...      ...        ...
35  0040107F C3         ret

其中,机器级代码行包括行号、虚拟地址、机器指令和汇编指令。

请回答下列问题。

(1) 计算机 M 是 RISC 还是 CISC?为什么?

(2) f1 的机器指令代码共占多少字节?要求给出计算过程。

(3) 第 20 条指令 cmp 通过 i 减 n-1 实现对 i 和 n-1 的比较。执行 f1(0) 过程中,当 i=0 时,cmp 指令执行后,进/借位标志 CF 的内容是什么?要求给出计算过程。

(4) 第 23 条指令 shl 通过左移操作实现了 power2 运算,在 f2 中能否也用 shl 指令实现 power2?为什么?

解析

本题在 2017-43 的 f1 函数之上,给出 x86 反汇编片段,考查 CISC vs RISC 的判别机器代码段长度计算cmp 后标志位推导、以及 整数移位不能套用到浮点数上 这一陷阱。

(1) M 是 RISC 还是 CISC?[2 分]

M 为 CISC。

判据: RISC 的核心特征是 指令定长(如 MIPS / RISC-V 32 位定长,ARM Thumb 16 位定长)。题表中 M 的指令长度参差不齐:

  • push ebp:1 字节(55H);
  • cmp dword ptr [ebp-0Ch], ecx:3 字节(39 4D F4H);
  • shl edx, 1:2 字节(D1 E2H)。

变长指令是 CISC(如 x86)的典型特征。配合"ebp / ecx / edx 等 32 位通用寄存器名称",可锁定为 x86(IA-32),是 CISC。

编者注(生僻术语): RISC vs CISC 的判别还有别的角度——指令数(RISC 少、CISC 多)、寻址方式(RISC 简单几种、CISC 多达十余种)、是否 load-store 架构(RISC 是、CISC 不一定)。指令长度是最直观的一个。

(2) f1 的机器代码总字节数 [2 分]

f1 第一条指令地址:0040 1020H(push ebp); 最后一条指令地址:0040 107FH(ret)。

ret 指令长度 = 1 字节(机器码 C3H),所以 f1 占据的地址区间是 [1020H, 1080H):

易错点: "+1" 别忘——字节范围 [a, b] 的长度是 b − a + 1,闭区间。漏掉就是 95B。

(3) 执行 f1(0) 时 cmp 后 CF 的值 [3 分]

Step 1. 算 cmp 的两个操作数。

执行 f1(0)n = 0n - 1 在 unsigned 算术下溢回最大值:

cmp 第一轮(i = 0):

Step 2. 用补码加法实现减法。

减法 = 加被减数补码:

实际加法器做:

Step 3. 求 CF。

加法器的进位输出 (最高位 0+0+0 没产生进位)。x86 减法约定下:

Step 4. 物理意义验证。

0 < FFFFFFFFH(无符号),借位发生 → CF = 1。✓

易错点: x86 的 CF 在减法里是"借位标志",规则与"加法的 Cout 直接做 CF" 相反。记忆法:减法 CF = 1 ↔ 被减数 < 减数(当作无符号)。

(4) f2 中能否用 shl 实现 power * 2?[3 分]

不能。

原因: shl 把整数的位作为整体左移 1 位(最低位补 0),等价于"乘 2"——但这只对 整数补码 / 无符号 表示成立。

float 的机器数不是单一权值的二进制串,而是 IEEE 754 编码:

[符号 S | 阶码 E | 尾数 M]
   1 位     8 位     23 位

整体左移会把:

  • 符号位移出(数据丢失),相邻的阶码最高位"补"进符号位 → 数被强行变正/变负;
  • 阶码错位 → 数量级跳变到完全无关的数;
  • 尾数最低位被填 0(这倒是无害)。

要让浮点数 ×2,正确做法是 阶码字段加 1——这是浮点 ×2 的硬件捷径,但 shl 不知道这种结构,所以失败。

编者注(生僻术语): x86 上浮点的乘法走 FPU / SSE 指令(如 mulssfmul),不是整数移位。现代编译器会发现 power *= 2 的右操作数是 2 的幂,对 int 优化成 shl,但对 float 维持 mulss ——它们的机器表示根本不同。

最后更新:

⚠️ 这道题暂未配可视化,欢迎在 CodeBrick 反馈区告诉我们你想看哪道题