第 3 章 指令系统¶
依据:袁春风《计算机组成原理》(2016 年版)第 3 章及配套自考大纲。下文编号指大纲“考核内容与考核要求”;教材算例为学习辅助,不是真题。
复习导航:大纲要求与笔记位置¶
| 大纲条目 | 层次 | 位置 | 学完应能做到 |
|---|---|---|---|
| 1 指令格式设计 | 识记、领会 | 第 1 节 | 说出各类地址数格式,解释指令基本信息与设计原则 |
| 2 指令系统设计 | 识记、领会 | 第 2 节 | 列出八种寻址方式,求有效地址,解释定长与扩展操作码,比较 RISC 与 CISC |
| 3 指令系统实例 | 领会 | 第 3 节 | 说明 MIPS 的指令格式、指令类型与寄存器组织 |
| 4 程序的机器级表示 | 领会 | 第 4 节 | 说明汇编与机器语言、高级语言与机器语言之间的对应关系 |
第 2 条涵盖本章主要内容,要求识记与领会。复习时分别掌握“有效地址”的求法和“扩展操作码前缀”的作用。
本章学习目标¶
第 2 章介绍数据编码,本章介绍指令编码:如何在有限的二进制位中表示操作、源和目的操作数,以及控制流信息。
全章四节从设计规则逐步转到具体程序:第 1、2 节介绍地址格式、扩展操作码、八种寻址方式和 RISC/CISC;第 3 节以 MIPS 说明 R/I/J 格式;第 4 节分析 C 语言分支、循环和数组的 MIPS 表示。计算时尤其注意相对寻址采用的 PC 基准,以及有效地址 EA 与操作数 M[EA] 的区别。
1 指令格式设计(1,识记、领会)¶
一条指令需要确定操作类型、源操作数位置、结果位置和下一条指令地址。若全部显式编码,指令会很长;通常顺序执行地址由 PC 更新规则隐含给出,遇到分支或跳转再修改 PC。按显式给出的操作数地址数,可分为以下四类格式:
| 显式地址数 | 常见语义示意 | 隐含内容 |
|---|---|---|
| 三地址 | \(A_3 \leftarrow A_1\ \text{op}\ A_2\) | PC 提供后继指令地址 |
| 二地址 | \(A_1 \leftarrow A_1\ \text{op}\ A_2\) | 其中一个源地址兼作结果目的地址(会覆盖原值) |
| 一地址 | \(\text{AC} \leftarrow \text{AC}\ \text{op}\ M[A]\) | 隐含使用累加器 AC 作另一操作数与结果寄存器 |
| 零地址 | 对栈顶两个元素运算并压回栈顶(或如 NOP、RET 无操作数) |
隐含使用操作数栈顶(或特定控制寄存器) |
源、目的字段应按题设解释。显式地址数减少,单条指令通常更短,但完成同一表达式可能需要更多指令。格式设计需权衡指令长度、寻址范围、译码规则和代码密度。
三个“字长”指不同概念:机器字长是 CPU 一次整数运算自然处理的位数(常等于通用寄存器宽度);指令字长是一条指令占用的位数;存储字长是一个主存编址单元或一次访存包含的位数。三者不一定相等。在按字节编址的机器上,32 位定长指令占 4 个字节,顺序取指时 \(\text{PC}\leftarrow\text{PC}+4\)。
2 指令系统设计(2,识记、领会)¶
2.1 操作数与寻址¶
指令的形式地址 \(A\) 受字段位宽限制,不一定直接等于操作数地址。寻址方式规定如何由 \(A\) 得到有效地址(EA)或操作数。大纲要求掌握以下八种方式,其中 \(R\) 表示寄存器内容,\(M[x]\) 表示主存 \(x\) 单元的内容:
| 方式 | 操作数/有效地址 EA | 典型用途与访存次数(不含取指) |
|---|---|---|
| 立即寻址 | 操作数 \(= A\)(无须算 EA) | 给寄存器赋常数;0 次访存 |
| 直接寻址 | \(\text{EA} = A\),操作数 \(= M[A]\) | 访问地址固定的全局变量;1 次访存 |
| 间接寻址 | \(\text{EA} = M[A]\),操作数 \(= M[M[A]]\) | 指针解引用;2 次访存(先读指针再读数) |
| 寄存器直接 | 操作数 \(= R[r]\) | 寄存器间高频运算;0 次访存,最快 |
| 寄存器间接 | \(\text{EA} = R[r]\),操作数 \(= M[R[r]]\) | 用寄存器存指针遍历内存;1 次访存 |
| 变址寻址 | \(\text{EA} = A + R[\text{index}]\),操作数 \(= M[\text{EA}]\) | 数组遍历:\(A\) 放数组首址,变址寄存器放元素偏移 |
| 基址寻址 | \(\text{EA} = R[\text{base}] + A\),操作数 \(= M[\text{EA}]\) | 程序重定位或访问结构体字段:基址寄存器固定,位移 \(A\) 可变 |
| 相对寻址 | \(\text{EA} = \text{PC} + A\) | 条件分支与位置无关代码,以取指更新后的 PC 为基准加补码偏移 |
计算有效地址时,重点区分以下两点:
- 变址与基址:两者都可表示为寄存器内容加形式地址,但用途不同。变址寻址常用于数组,\(A\) 表示首址,寄存器随下标变化;基址寻址常用于重定位或以某个基址访问数据,由寄存器提供基址,\(A\) 提供位移。应结合题设判断,不能只看加法形式。
- 相对寻址的 PC 基准:教材模型按取指后、已指向下一条指令的 PC 计算 \(\text{目标地址} = \text{PC} + \text{偏移量}\)。题目若另行规定,应采用其基准;不要未经确认就用当前指令首地址代入。
自编例:设形式地址 \(A=100\)、寄存器 \(R=20\),且 \(M[100]=300\)、\(M[300]=9\)。立即寻址的操作数为 100;直接寻址的有效地址为 100,操作数为 \(M[100]=300\);一次间接寻址的有效地址为 300,操作数为 \(M[300]=9\)。基址或变址寻址得到有效地址 \(100+20=120\),操作数还需读取 \(M[120]\)。有效地址表示访存位置,操作数是该位置存放的值。
2.2 操作类型与控制流¶
各家指令集的操作类型大同小异:数据传送(如 lw/sw、mov)、算术逻辑运算、移位操作,以及改变程序顺序的转移(分支)与过程调用。
转移、过程调用与中断的区别在于保存什么状态。无条件/条件转移改变 PC,通常不保存返回地址;过程调用(转子指令)需先把返回地址保存在栈或专用寄存器中,如 MIPS 的 $ra,供返回指令恢复;硬件中断/异常还需按体系结构保存断点与有关处理器状态,以便处理后恢复执行。
条件分支依体系结构采用不同机制。x86 可先用比较指令更新标志:无符号比较查看 CF、ZF;带符号比较需结合 SF 与 OF,即 SF ⊕ OF,以修正减法溢出对符号的影响。MIPS 可用 beq/bne 比较寄存器是否相等,也可用 slt 将比较结果写入通用寄存器,再据此分支。
2.3 操作码编码¶
固定指令总长下,定长操作码统一使用 \(k\) 位,可表示 \(2^k\) 条指令,便于译码;扩展操作码则利用较少地址字段所腾出的位,形成更长操作码。扩展时必须保证短操作码不是任何长操作码的前缀,避免译码歧义。指令总长固定,不代表操作码长度也固定。
例如,指令字长 16 位、每个地址码 4 位,三地址字段占 \(3 \times 4 = 12\) 位,剩余 4 位操作码共有 \(2^4 = 16\) 个编码。若使用 15 个,保留 1111 作为扩展前缀,则再借用 4 位,可得到 \(1 \times 2^4 = 16\) 个二地址编码。二地址若仍使用 15 个、保留 1111 1111,就可继续扩展出 16 个一地址编码。一般地,上级保留 \(m\) 个前缀、下级增加 \(b\) 位,可得到 \(m \times 2^b\) 个编码。因此,定长指令字 \(\ne\) 定长操作码。
2.4 指令系统风格¶
按操作数的主要存放位置,可区分累加器型、栈型和通用寄存器型。通用寄存器型还可比较算术指令能否直接访问主存。教材再从以下典型特点对照 RISC(精简指令集)与 CISC(复杂指令集):
| 比较 | RISC 典型特征 | CISC 典型特征 |
|---|---|---|
| 指令与格式 | 只留高频简单指令,定长指令字,字段位置规整 | 指令庞大复杂,指令长度可变,操作码与字段长短不一 |
| 寻址方式 | 少而精(3~5 种) | 繁多复杂(可达十余种) |
| 访存规矩 | Load/Store 结构:只有装入/存储指令能访存,运算一律在寄存器间完成 | 允许 add 等运算指令直接带主存操作数 |
| 控制器与流水线 | 教材典型模型使用较多通用寄存器与硬连线控制,规整格式便于流水化 | 教材典型模型较多采用微程序控制,复杂指令的流水化实现更复杂 |
按教材列出的典型特点比较即可。RISC 的规整设计有利于流水化,但 CPI 仍受访存缺失、冒险和实现方式影响,不能一概视为 1。
3 MIPS 指令集实例(3,领会)¶
教材采用 32 位 MIPS 示例:指令长 32 位(4 字节),有 32 个 32 位通用寄存器,编号 0~31,寄存器字段需 5 位。0 号寄存器 $zero($0)恒为 0。基本指令分为 R 型、I 型、J 型,高 6 位为操作码 op:
| 类型 | 字段切分(高位 → 低位,共 32 位) | 典型指令与说明 |
|---|---|---|
| R 型 | op(6) + rs(5) + rt(5) + rd(5) + shamt(5) + funct(6) |
寄存器间运算:op 全为 0,具体干什么看低 6 位功能码 funct;rd ← rs op rt |
| I 型 | op(6) + rs(5) + rt(5) + imm(16) |
带 16 位立即数的运算(addi/andi)、访存(lw/sw)与条件分支(beq/bne),目的或源在 rt |
| J 型 | op(6) + addr(26) |
无条件跳转 j 与调用 jal;jal 将返回地址 PC+4 存入 31 号寄存器 $ra |
以下四类 MIPS 指令需要分别确认寄存器字段、地址计算和立即数扩展规则:
- R 型运算(如
add $t0, $t1, $t2):汇编的目的寄存器$t0写在首位,在机器码中对应rd;源寄存器$t1、$t2分别对应rs、rt。移位指令的移位量由 5 位shamt字段给出。 - I 型访存(如
lw $t0, 12($s0)与sw $t0, 12($s0)):采用基址寻址,有效地址 \(\text{EA} = R[\text{\$s0}] + \text{SignExt}(12)\)。括号外的12是字节偏移量:若遍历 32 位int数组(每元素占 4 字节),下标每加 1,字节偏移要加 4。 - I 型立即数扩展:
addi、lw、sw、beq等指令的 16 位立即数字段按符号扩展为 32 位(SignExt);andi、ori的立即数作为位掩码,采用零扩展(ZeroExt)。 - 分支与跳转目标地址:本例 MIPS 指令按 4 字节对齐,目标地址最低两位为
00B。分支位移或跳转目标字段省略这两位,计算字节地址时再左移 2 位(乘 4),并按各自规则与 PC 组合: - I 型条件分支(
beq/bne):相对寻址,以PC + 4(下一条指令地址)为基准加上字偏移乘 4: $\(\text{分支目标地址} = (\text{PC} + 4) + (\text{SignExt}(\text{imm16}) \ll 2)\)$ 例如,当前beq指令地址为1000H、imm16 = 3,则目标地址为 \(1000\text{H} + 4 + 3\times4 = 1010\text{H}\)。 - J 型无条件跳转(
j/jal):伪直接寻址,取PC + 4的最高 4 位,拼上指令里的 26 位addr,末尾再补上00B,合起来正好 32 位字节地址: $\(\text{跳转目标地址} = (\text{PC} + 4)_{31..28} \ \Vert\ \text{addr26} \ \Vert\ 00\text{B}\)$
4 程序的机器级表示(4,领会)¶
看懂了单条 MIPS 指令,再看编译器怎么把 C 语言的选择(if-else)和循环(for/while)翻成机器代码。
以 if (a == b) c = d + e; else c = d - e; 为例,一种常见翻译是先用 bne 检查不相等,成立则跳到 else 执行减法;否则顺序执行加法,再用 j 跳过 else,最后汇合。因此,还原条件时应结合跳转方向和标号,不能直接把分支指令的条件当作源程序条件。
分析循环汇编时,可按以下顺序追踪:
- 检查
loop:之前的初始化,确定累加器、数组基址和偏移变量。 - 检查每轮更新的量与步长。下标加
1表示前进一个元素;32 位元素的字节偏移通常加4。 - 检查
beq/bne的条件及其位置,区分先判断后执行与先执行后判断,再计算迭代次数。
本章习题 10、11、12 可用于练习。
5 考核要求¶
本章共 4 条考核条目:第 1、2 条(指令格式与指令系统设计)兼有识记与领会,第 3、4 条(MIPS 实例与机器级程序表示)要求领会。重点练习扩展操作码计数、寻址方式下的有效地址与操作数计算、RISC/CISC 对比,以及 MIPS 循环分析;运行时间可联系第 1 章 CPI 公式计算。
6 教材本章习题¶
题目取自教材第 3 章“习题”(共 12 题),答案取自教材附录“部分习题解答”(附录收录第 3、4、6、7、8、9、10、11、12 题,其余题目请对照教材自行完成)。
6.1 概念与简答¶
1. 给出以下概念的解释说明。
指令、操作码、地址码、程序计数器 PC
寻址方式、有效地址、立即寻址、直接寻址
间接寻址、寄存器直接寻址、寄存器间接寻址、变址寻址
变址寄存器、相对寻址、基址寻址、基址寄存器
通用寄存器、CISC、RISC
答案与解析
教材附录未收本题解答,请对照教材自行完成。
2. 简单回答下列问题。
(1)一条指令中应该显式或隐式地给出哪些信息?
(2)什么是“汇编”过程?什么是“反汇编”过程?
(3)CPU 如何确定指令中各个操作数的类型、长度以及所在地址?
(4)哪些寻址方式下的操作数在寄存器中?哪些寻址方式下的操作数在存储器中?
(5)基址寻址方式和变址寻址方式的作用各是什么?有何相同点和不同点?
(6)RISC 处理器的特点有哪些?
(7)CPU 中标志寄存器的功能是什么?有哪几种基本标志?
(8)转移指令和调用(转子)指令的区别是什么?返回指令是否需要有地址码字段?为什么?
答案与解析
教材附录未收本题解答,请对照教材自行完成。
6.2 指令格式与寻址¶
3. 假定指令系统中有一条转移指令采用相对寻址方式,共占两个字节,第一字节是操作码,第二字节是相对位移量(用补码表示)。CPU 每次从内存只能取一个字节,主存按字节编址。假设执行到某转移指令时 PC 的内容为 8000H(即该转移指令的地址为 8000H),执行该转移指令后要求转移到 7FB0H 处的指令执行,则该转移指令第二字节的内容应该是什么?
答案与解析
参考答案: 转移指令起始于 8000H,CPU 先取第一字节操作码,PC 增至 8001H;再取第二字节相对位移量,PC 增至 8002H。进入执行阶段计算目标地址时,基准 PC 已经是 8002H。由相对寻址公式 \(\text{转移目标地址} = (\text{PC}) + \text{位移量} = 7\text{FB0H}\),算出位移量 \(= 7\text{FB0H} - 8002\text{H} = -52\text{H}\)。将 \(-52\text{H} = -0101\ 0010\text{B}\) 转成 8 位补码(\(100\text{H} - 52\text{H}\),或数值位取反末位加 1),得到 AEH(1010 1110B)。故该转移指令第二字节的内容为 10101110(或 AEH)。
4. 假设地址为 800CH 的内存单元中的内容为 78F0H,地址为 78F0H 的内存单元的内容为 654BH,而 654BH 单元的内容为 869CH。
说明以下各情况下操作数的有效地址和操作数各是什么?
(1)操作数采用变址寻址,变址寄存器的内容为 12,指令中给出的形式地址为 8000H。
(2)操作数采用一次间接寻址,指令中给出的地址码为 78F0H。
(3)操作数采用寄存器间接寻址,指令中给出的寄存器编号为 8,8 号寄存器的内容为 78F0H。
答案与解析
参考答案: (1)有效地址为 \(000CH+8000H=800CH\),操作数为 \(78F0H\)。
(2)有效地址为 \(78F0H\) 所指内存单元内容 \(654BH\),操作数为 \(869CH\)。
(3)有效地址为 \(78F0H\),操作数为 654BH。
5. 通过查资料了解 Intel 80x86 微处理器和 MIPS 处理器中各自提供了哪些加法指令,说明每条加法指令的汇编形式、指令格式和功能,并比较加、减运算指令在这两种指令系统中不同的设计方式,包括不同的溢出处理方式。
答案与解析
教材附录未收本题解答,请对照教材自行完成。
6. 某计算机指令系统采用定长指令字格式,指令字长 16 位,每个操作数的地址码长 6 位。指令分二地址、单地址和零地址三类。若二地址指令有 \(k_{2}\) 条,无地址指令有 \(k_{0}\) 条,则单地址指令最多有多少条?
答案与解析
参考答案: 假设单地址指令有 \(k_{1}\) 条,则 \(((16-k_{2})\times2^{6}-k_{1})\times2^{6}=k_{0}\),所以 \(k_{1}=(16-k_{2})\times2^{6}-k_{0}/2^{6}\)。
7. 某计算机字长为 16 位,主存地址空间大小为 128 KB,按字编址。采用单字长定长指令格式,指令各字段定义如下:
| 15~12 | 11~9 | 8~6 | 5~3 | 2~0 |
|---|---|---|---|---|
| OP | Ms | Rs | Md | Rd |
Ms、Rs 为源操作数字段,Md、Rd 为目的操作数字段。转移指令采用相对寻址方式,相对偏移量用补码表示。寻址方式定义如下表所示。
| Ms / Md | 寻址方式 | 助记符 | 含义 |
|---|---|---|---|
| 000B | 寄存器直接 | Rn | 操作数 = \(R[Rn]\) |
| 001B | 寄存器间接 | (Rn) | 操作数 = \(M[R[Rn]]\) |
| 010B | 寄存器间接、自增 | (Rn) + | 操作数 = \(M[R[Rn]]\), \(R[Rn] \leftarrow R[Rn] + 1\) |
| 011B | 相对 | D(Rn) | 转移目标地址 = \(PC + R[Rn]\) |
(注:M[x] 表示存储器地址 x 中的内容,R[x] 表示寄存器 x 中的内容)请回答下列问题:
(1)该指令系统最多可有多少条指令?该计算机最多有多少个通用寄存器?存储器地址寄存器(MAR)和存储器数据寄存器(MDR)至少各需要多少位?
(2)转移指令的目标地址范围是多少?
(3)若操作码 0010B 表示加法操作(助记符为 add),寄存器 R4 和 R5 的编号分别为 100B 和 101B,R4 的内容为 1234H,R5 的内容为 5678H,地址 1234H 中的内容为 5678H,地址 5678H 中的内容为 1234H,则汇编语句“add(R4),(R5)+”(逗号前为第一源操作数,逗号后为第二源操作数和目的操作数)对应的机器码是什么(用十六进制表示)?该指令执行后,哪些寄存器和存储单元的内容会改变?改变后的内容是什么?
答案与解析
参考答案: (1)单字长指令的操作码字段 OP 占 4 位,最多可表示 \(2^4 = 16\) 条指令;寄存器编号字段 Rs/Rd 占 3 位,最多有 \(2^3 = 8\) 个通用寄存器。主存地址空间 128 KB、字长 16 位(2 B)且按字编址,共有 \(128\ \text{KB} / 2\ \text{B} = 64\ \text{K} = 2^{16}\) 个存储字单元,寻址需要 16 位地址,故 MAR 至少 16 位;存储字长等于机器字长 16 位,故 MDR 至少 16 位。
(2)PC 与通用寄存器同为 16 位,按相对寻址公式 \(\text{PC} + R[Rn]\) 将两个 16 位量模 \(2^{16}\) 相加,足以覆盖全部 16 位地址,故转移目标地址范围为 0000H~FFFFH(整片地址空间)。
(3)把各字段拼起来就是机器码。add 对应 op 字段,取 0010B;(R4)的寻址方式字段为 001B,R4 的编号为 100B;(R5)+ 的寻址方式字段为 010B,R5 的编号为 101B。拼成 0010 001 100 010 101B,十六进制即 2315H。
机器码好拼,动作容易写错,单独说清。(R4) 是寄存器间接,操作数在 M[R[R4]];(R5)+ 同样是寄存器间接,只是取完数之后 R5 自增。写回的目的地址是 M[R[R5]],不是 M[R5]——记号里 M[R5] 的意思是“以寄存器编号 5 为地址的那个单元”,写成它就把间接这一层丢了。
把两个有效地址在访存之前先锁存下来,动作就没有歧义:
EA1 = R[R4] = 1234H,EA2 = R[R5] = 5678H;- 取数:
M[EA1] = 5678H,M[EA2] = 1234H; - 相加:1234H + 5678H = 68ACH;
- 写回
M[EA2],即 M[5678H] ← 68ACH; - 同时
R[R5] ← R[R5] + 1 = 5679H。
要害在最后两步互不干扰:写回用的是加法之前就已锁存的 EA2(5678H),R5 的自增走另一条通路。若图省事拿自增后的 R5 当地址,结果会被写到 5679H 去——那是毫不相干的一个单元。
自增步长为什么是 1 而不是 2,见第(1)问:该机地址空间 128 KB、字长 16 位、按字编址,一个地址就是 16 位字,所以前进一个单元记作 +1。换成按字节编址的机器访问 16 位字,步长必须改成 2,否则会踩坏相邻的半字。
8. 有些计算机提供了具有如下功能的指令,能从一个 32 位寄存器中抽取其中任意一个位串置于另一个寄存器的低有效位上,并在高位补 0,如下图所示。
MIPS 指令系统中没有这样的指令,请写出最短的一个 MIPS 指令序列来实现这个功能,要求 \(i=5,j=22\),操作前后的寄存器分别为 \(\mathrm{s}0\) 和 \(\mathrm{s}2\)。
31 j i 0
源寄存器 +---------------+------+---------------+
| | 位串 | |
+---------------+------+---------------+
|
| 抽取第 j~i 位,右移到低有效位,高位补 0
v
31 0
目的寄存器 +--------------------+--------------+
| 高位全部补 0 | 位串 |
+--------------------+--------------+
答案与解析
参考答案: 这里要注意两点:第二条右移指令绝不能用算术右移 sra,否则高位补进来的是符号位,没法保证一定补 0;另外,第一条指令的目的寄存器和第二条指令的源寄存器都只能用 $s2,不能借用其他寄存器中转,以免踩坏别的寄存器里原有的值。
(补充,教材附录未给指令序列) 以 i=5、j=22 为例(要保留第 22~5 位共 18 位,源 $s0、目的 $s2):
sll $s2, $s0, 9 # 第 22 位顶到最高位,第 5 位落到第 14 位
srl $s2, $s2, 14 # 这 18 位落到 0~17 位,高位补 0
两条就是最短:sll 把位串平移到高位,srl 再把它落回低位,全程用逻辑右移,所以高位一定补 0;答案里说的「不能用 sra、两处都只能用 $s2」正好被这两条指令用上。
6.3 机器级程序¶
9. 除了硬件乘法器外,还可以用移位指令和加法指令来实现乘法运算。在乘以较小的常数时,这种办法很有效。
假设 $s0 中为一个无符号整数,现要将 $s0 的内容与 6 相乘,乘积存入 $s1 中。请写出一段指令条数最少且不包括乘法指令的 MIPS 代码。
答案与解析
参考答案: 一个数 x 乘以 6,相当于 \(4x+2x\),而 4x 可以通过将 x 左移两位来实现,2x 可以通过将 x 左移一位来实现。这样就只要用两条左移指令和一条加法指令来实现乘 6 操作。以此类推,当乘以一个较小的常数时,只要将这个较小的常数分解成若干个 2 的幂次相加,就可以用若干条左移指令和一条加法指令来实现乘法运算。可用以下指令序列实现题目要求。
sll $s1, $s0, 2 #将 $s0 的内容左移两位,送 $s1
sll $s0, $s0, 1 #将 $s0 的内容左移一位,送 $s0
addu $s1, $s1, $s0 #将 $s1 和 $s0 的内容相加,送 $s1
10. 以下程序段是某个过程对应的指令序列。入口参数 int a 和 int b 分别置于 $a0 和 $a1 中,返回参数是该过程的结果,置于 $v0 中。
要求为以下 MIPS 指令序列加注释,并简单说明该过程的功能。
add $t0, zero, $zero
loop: beq $a1, $zero, finish
add $t0, $t0, $a0
sub $a1, $a1, 1
j loop
finish: addi $t0, $t0, 100
add $v0, $t0, $zero
答案与解析
参考答案:
add $t0, zero, $zero #将寄存器 $t0 置 0
loop: beq $a1, $zero, finish #若 $a1 的值等于 0,则转 finish 处
add $t0, $t0, $a0 #将 $t0 和 $a0 的内容相加,送 $t0
sub $a1, $a1, 1 #将 $a1 的值减 1
j loop #无条件转到 loop 处
finish: addi $t0, $t0, 100 #将 $t0 的内容加 100
add $v0, $t0, $zero #将 $t0 的内容送 $v0
该过程的功能是计算“ \(a \times b + 100\)”。
11. 下列指令序列用来对两个数组进行处理,并产生结果存放在 $v0 中。
假定每个数组有 2500 个字,其数组下标为 0 到 2499。两个数组的基地址分别存放在 $a0 和 $a1 中,数组长度分别存放在 $a2 和 $a3 中。要求为以下 MIPS 指令序列加注释,并简单说明该过程的功能。假定该指令序列运行在一个时钟频率为 2 GHz 的处理器上,add、addi 和 sll 指令的 CPI 为 1;lw 和 bne 指令的 CPI 为 2,则最坏情况下运行所需时间是多少秒?
sll $a2, $a2, 2
sll $a3, $a3, 2
add $v0, $zero, $zero
add $t0, $zero, $zero
outer: add $t4, $a0, $t0
lw $t4, 0($t4)
add $t1, $zero, $zero
inner: add $t3, $a1, $t1
lw $t3, 0($t3)
bne $t3, $t4, skip
addi $v0, $v0, 1
skip: addi $t1, $t1, 4
bne $t1, $a3, inner
addi $t0, $t0, 4
bne $t0, $a2, outer
答案与解析
参考答案:
sll $a2, $a2, 2 # $a2 的内容左移 2 位,即乘 4
sll $a3, $a3, 2 # $a3 的内容左移 2 位,即乘 4
add $v0, $zero, $zero # $v0 初始化为 0
add $t0, $zero, $zero # $t0 初始化为 0
outer: add $t4, $a0, $t0 #计算数组 1 当前元素的地址
lw $t4, 0($t4) #数组 1 当前元素存放在 $t4
add $t1, $zero, $zero # $t1 初始化为 0
inner: add $t3, $a1, $t1 #计算数组 2 当前元素的地址
lw $t3, 0($t3) #数组 2 当前元素存放在 $t3
bne $t3, $t4, skip # $t3 和 $t4 的内容不相等,则转 skip
addi $v0, $v0, 1 # $v0 加 1
skip: addi $t1, $t1, 4 # $t1 加 4
bne $t1, $a3, inner #数组 2 未处理完,继续转 inner 执行
addi $t0, $t0, 4 # $t0 加 4
bne $t0, $a2, outer #数组 1 未处理完,继续转 outer 执行
该过程的功能是统计两个数组中相同元素的个数(多次相等则重复计数)。最坏情况是两个数组的所有元素全部相等,此时内层循环每次都要执行 addi $v0, $v0, 1。按 add/addi/sll 的 \(\text{CPI}=1\)、lw/bne 的 \(\text{CPI}=2\) 累加:循环前 4 条指令占 4 个周期;外层每轮开头 3 条指令占 \(1+2+1=4\) 个周期,内层每轮 6 条指令占 \((1+2+2+1) + (1+2) = 9\) 个周期(跑 2 500 轮),外层末尾 2 条指令占 \(1+2=3\) 个周期。最坏情况下总时钟周期数为 \(4 + [4 + (6 + 3) \times 2500 + 3] \times 2500 = 56\,267\,504\) 个。主频 2 GHz 对应时钟周期 \(T = 1 / (2\ \text{GHz}) = 0.5\ \text{ns}\),故最坏总执行时间为 \(56\,267\,504 \times 0.5\ \text{ns} = 28\,133\,752\ \text{ns} \approx 0.028\ \text{s}\)。
12. 以下程序段是某个过程对应的 MIPS 指令序列,其功能为复制一个存储块中的数据到另一个存储块中,存储块中每个数据的类型为 int,源数据块和目的数据块的首地址分别存放在 $a0 和 $a1 中,复制的数据个数存放在 $v0 中,作为返回参数返回给调用过程。
假定在复制过程中遇到 0 就停止复制,最后一个 0 也需要复制,但不被计数。已知程序段中有多个 Bug,请找出它们并修改之。
addi v0, zero, 0
loop: lw v1, 0(a0)
sw v1, 0(a1)
addi a0, a0, 4
addi a1, a1, 4
beq v1, zero, loop
beq v1, zero, loop
答案与解析
参考答案: 修改后的代码如下:
addi $v0, $zero, 0
loop: lw $v1, 0($a0)
sw $v1, 0($a1)
beq $v1, $zero, exit
addi $a0, $a0, 4
addi $a1, $a1, 4
addi $v0, $v0, 1
j loop
exit:
7 自编客观题(补充)¶
以下 15 题按 2024 年 10 月、2025 年 4 月两卷客观题考点自编,不是教材原题;只作检索式回忆用。
7.1 单项选择题¶
1. 指令格式中只给出一个地址字段时,这种一地址指令通常隐含使用
答案与解析
参考答案: D。一地址把累加器当作另一个源操作数与结果存放处,隐含栈顶的是零地址指令。
2. 采用立即寻址方式时,操作数位于
答案与解析
参考答案: A。立即数就写在指令里,无须再求有效地址;B 是直接寻址,D 是寄存器间接寻址。
3. 执行 lw $s1,200($s2) 后,$s1 中得到的是
答案与解析
参考答案: C。lw 把有效地址处的字装入寄存器,有效地址是基址寄存器内容加符号扩展的位移。
4. 设计扩展操作码时的硬性要求是
答案与解析
参考答案: A。前缀相同会让译码产生歧义;指令总长固定时同样可以用扩展操作码,B 不成立。
5. 设地址字段 A=100H,R=20H,M[100H]=300H,M[300H]=12H,则一次间接寻址取到的操作数是
答案与解析
参考答案: A。间接寻址先算 EA=M[A]=300H,再取 M[300H]=12H;C 是有效地址,不是操作数。
6. 相对寻址方式的基准是
答案与解析
参考答案: A。有效地址由 PC 加位移得到,代码整体搬家后仍能正确转移;B、C 分别是变址与基址的基准。
7. 两字节转移指令存放在 8000H、8001H,执行后要转到 7FB0H,则第二字节的补码相对位移量是
答案与解析
参考答案: C。取完两字节后 PC=8002H,位移=7FB0H-8002H=-52H,八位补码为 AEH。
8. 下列寻址方式中,操作数不在主存的是
答案与解析
参考答案: B。寄存器寻址的操作数就在寄存器里;寄存器间接与变址的操作数都在主存,只是有效地址来源不同。
9. MIPS 的 andi 指令在运算前对 16 位立即数作
答案与解析
参考答案: B。逻辑运算按位进行,高位补 0,andi、ori 都是零扩展;addi 及 lw/sw、beq 的立即数字段才按符号扩展。
10. 下列特征中属于 RISC 典型特征的是
答案与解析
参考答案: B。RISC 让运算只在寄存器之间进行;A、C、D 都是 CISC 的典型倾向。
7.2 填空题¶
11. 指令字长 16 位、每个地址码 6 位,采用定长指令字格式时,二地址指令最多有 ___ 条。
答案与解析
参考答案: 16
12. MIPS 的 lw、sw、beq 等指令采用 ___ 型格式,操作码 6 位、两个寄存器字段各 5 位、立即数 16 位。
答案与解析
参考答案: I
13. 指令中给出的形式地址为 100H、变址寄存器内容为 20H,采用变址寻址时的有效地址是 ___。
答案与解析
参考答案: 120H
14. 一条指令必须给出操作类型、源操作数、结果位置,以及通常由 PC 更新得到的 ___。
答案与解析
参考答案: 后继指令地址
15. 某 MIPS 处理器当前指令地址为 1000H,beq 的 imm16 为 3,则分支目标地址是 ___。
答案与解析
参考答案: 1010H(1000H+4+3×4)
8 闭卷复习与跨章联系(补充)¶
一、闭卷自答(合上书逐题口述)
- 一条指令要显式或隐式给出哪些信息?三地址、二地址、一地址、零地址各隐含了什么?
- 八种寻址方式的有效地址怎么算?变址与基址形式相近,靠什么区分?用相对寻址必须核对哪两点?
- 扩展操作码为什么不能让短码成为另一条有效操作码的前缀?定长指令字还能用扩展操作码吗?
- RISC 与 CISC 在指令格式、寻址方式、访存方式和流水线实现上各有什么倾向?
- MIPS 的 R 型、I 型、J 型各有哪些字段?
lw的有效地址与beq的目标地址怎么算? - 高级语言的选择结构与循环落到汇编是什么形态?拿到一段机器码,怎样追出变量的值和控制流?
二、本章易错
- 算相对寻址偏移量时,取指阶段结束后 PC 已经指向下一条指令(如两字节指令取完后 \(\text{PC} + 2\),MIPS 指令取完后 \(\text{PC} + 4\)),别拿当前指令自己的首地址去减目标地址(第 2.1、3 节)。
- 定长指令字(所有指令总位数相同)与定长操作码不是一回事,16 位定长指令照样能用扩展操作码,只需保证短码不当长码前缀(第 2.3 节)。
- MIPS 的 16 位立即数不是一刀切做符号扩展:
addi/lw/sw/beq做符号扩展,而按位逻辑运算andi/ori做零扩展(第 3 节)。
三、本章骨架
| 板块 | 内容 | 一句话抓手 |
|---|---|---|
| 格式与寻址(第 1—2 节) | 操作码、地址字段、八种有效地址 | 地址数越少隐含越多;短码不得作前缀 |
| MIPS 实例(第 3 节) | R、I、J 三型字段与目标地址算法 | 分支按 PC+4+位移×4,跳转拼接 26 位 |
| 机器级表示(第 4 节) | if、循环、数组的汇编形态 | 先追寄存器与存储地址,再沿分支还原控制流 |
四、跨章指路