Skip to content

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

计算机组成原理2014年综合题12分

题目

某程序中有如下循环代码段 P:“for (int i=0; i<N; i++) sum += A[i];”。假设编译时变量 sum 和 i 分别分配在寄存器 R1 和 R2 中。常量 N 在寄存器 R6 中,数组 A 的首地址在寄存器 R3 中。程序段 P 起始地址为 08048100H,对应的汇编代码和机器代码如下表所示。

编号地址机器代码汇编代码注释
108048100H00022080Hloop: sll R4, R2, 2(R2)<<2 → R4
208048104H00083020Hadd R4, R4, R3(R4) + (R3) → R4
308048108H8C850000Hload R5, 0(R4)((R4) + 0) → R5
40804810CH00250820Hadd R1, R1, R5(R1) + (R5) → R1
508048110H20420001Hadd R2, R2, 1(R2) + 1 → R2
608048114H1446FFFAHbne R2, R6, loopif (R2)≠(R6) goto loop

执行上述代码的计算机 M 采用 32 位定长指令字,其中分支指令 bne 采用如下格式:

3126Op6 bits2521Rs5 bits2016Rd5 bits150OFFSET16 bits

Op 为操作码,Rs 和 Rd 为寄存器编号,OFFSET 为偏移量,用补码表示。请回答下列问题,并说明理由。

(1) M 的存储器编址单位是什么?

(2) 已知 sll 指令实现左移功能,数组 A 中每个元素占多少位?

(3) 题 44 表中 bne 指令的 OFFSET 字段的值是多少?已知 bne 指令采用相对寻址方式,当前 PC 内容为 bne 指令地址,通过分析题 44 表中指令地址和 bne 指令内容,推断出 bne 指令的转移目标地址计算公式。

(4) 若 M 采用如下“按序发射、按序完成”的 5 级指令流水线:IF(取指)、ID(译码及取数)、EXE(执行)、MEM(访存)、WB(写回寄存器),且硬件不采取任何转发措施,分支指令的执行均引起 3 个时钟周期阻塞,则 P 中那些指令的执行会由于数据相关而发生流水线阻塞?哪条指令的执行会发生控制冒险?为什么指令 1 的执行不会因为与指令 5 的数据相关而发生阻塞?

解析

本题把 指令格式 + 编址单位 + 相对寻址 + 流水线冒险 4 块知识串到一个 MIPS 风格的循环上。整体思路:

  • 由相邻指令地址差倒推编址单位(与 CPI 无关);
  • sll 指令的左移位数告诉我们数组元素的字宽;
  • bne 是相对寻址,要把 PC 自增、OFFSET 符号扩展、再乘 4 算到字节单位上;
  • 数据冒险逐条排查,分支冒险是结构性的(fetch 时还不知道目标)。

(1) 存储器编址单位 [2 分]

计算机 M 是 32 位定长指令字,每条指令 4B。题表中相邻指令地址差:

4 个地址单位刚好对应 4B → 每个地址单位 = 1B → 按字节编址

(2) 数组 A 中每个元素的位数 [2 分]

指令 1 是 sll R4, R2, 2,把循环变量 i(在 R2)左移 2 位 → 乘以 4 → 写入 R4 作为偏移;指令 2 把这个偏移加上数组首地址 R3,得到 &A[i]

也就是说:"i 增 1 → 偏移地址增 4 字节"——数组每个元素占 4 字节。配合按字节编址:

(3) bne 的 OFFSET 字段与目标地址公式 [3 分]

Step 1. 提取 OFFSET。

bne 机器码 = 1446 FFFAH = 0001 0100 0100 0110 1111 1111 1111 1010B。指令格式中低 16 位是 OFFSET:

按 16 位补码解读:FFFAH 取反 +1 = 0006HOFFSET = −6

Step 2. 反推目标地址公式。

bne 自身在 08048114H,其要跳到 08048100H(loop 标签)。fetch 完 bne 后 PC 自动 + 4:

目标与 PC(取指后)之差:

OFFSET = −6 而真实字节位移 = −24,比例 4 倍 → OFFSET 以"指令字"为单位,要 ×4 才是字节单位

编者注(生僻术语): 这是 MIPS 风格的"PC-相对、字对齐"寻址。指令 4B 对齐意味着字节位移的最低 2 位永远是 0,索性在指令编码层面省掉 → OFFSET 用作"指令数偏移",硬件再左移 2 位(×4)。代价是 OFFSET 寻址范围 ×4,扩展到 ±128KB。

(4) 流水线阻塞分析 [4 分]

逐条排查数据相关:

指令读寄存器写寄存器数据相关源是否阻塞
1 sll R4, R2, 2R2R4
2 add R4, R4, R3R4, R3R4R4 来自 I1✅ 阻塞
3 load R5, 0(R4)R4R5R4 来自 I2✅ 阻塞
4 add R1, R1, R5R1, R5R1R5 来自 I3✅ 阻塞
5 add R2, R2, 1R2R2
6 bne R2, R6R2, R6R2 来自 I5✅ 阻塞

故数据相关阻塞发生在第 2、3、4、6 条指令。

控制冒险:

第 6 条 bne 是分支指令,在 IF 之后需要等到执行结果(决定跳还是不跳)才能确定下一条指令地址 → 第 6 条引起 3 个周期的控制冒险

为什么 I1(下一轮)不会因为 I5 阻塞?

跨循环考虑:上一轮的 I5 写 R2,下一轮的 I1 读 R2,看似数据相关。但夹在它们之间的 I6(bne)已经引起了 3 个周期的控制冒险阻塞——这 3 个周期足够让 I5 的 WB 完成,等下一轮 I1 进入 ID 时 R2 早已写完。

易错点: 别混淆"数据冒险阻塞数"和"控制冒险阻塞数"。本题说"分支指令引起 3 个周期阻塞",这是控制冒险(因为不知道下一条指令地址),与数据冒险(无转发时通常 3 周期)刚好匹配——所以本题里"控制冒险" oneself 同时也覆盖掉了 I5 → I1 的潜在数据冒险。

【评分说明】若考生回答"因为指令 1 和 2、2 和 3、3 和 4、5 和 6 发生数据相关,发生阻塞的指令为第 2、3、4、6 条",同样给 3 分。答对 3 个以上给 3 分,部分正确酌情给分。

最后更新:

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