重点内容:
指令格式(R/I/J型,各字段作用)
操作码编码方案
寻址方式
跳转指令(PC相对寻址)
CISC和RISC的比较
4.1 指令格式
定长操作码、扩展操作码、操作类型
指令:计算机执行某种操作的命令。 指令系统 / 指令集:一台计算机所有指令的集合,位于硬件和软件的交界面上。
4.1.1 指令的基本格式
指令 = 操作码字段 + 地址码字段
- 操作码:操作的性质和功能
- 地址码:被操作信息的地址
指令长度:一条指令所含二进制代码的位数
指令长度和机器字长没有固定的关系。(半字长指令、单子长指令、双字长指令)
定长指令字结构:所有指令的长度都相等。执行速度快,控制简单
变长指令字结构:指令长度随指令功能而异。但是多为字节的整数倍
指令分类:
- 零地址指令:
OP无需操作数,或者运算数在堆栈中 - 一地址指令:
OP A1有两种可能- 读和写都在同一个操作数:
A1 ← OP(A1) - 隐含目的地地址的双操作数指令,如 ACC:
ACC ← ACC OP A1
- 读和写都在同一个操作数:
- 二地址指令:
OP A1 A2,表示A1 ← A1 OP A2 - 三地址指令:
OP A1 A2 A3,表示A3 ← A1 OP A2 - 四地址指令:
OP A1 A2 A3 A4,表示A3 ← A1 OP A2且下一条指令地址为A4$$\bigstar \mathbf{IMPORTANT}\bigstar$$ MIPS 指令格式:都是32位宽,按字地址对齐
R-Type:op[6] rs[5] rt[5] rd[5] shamt[5] funct[6]
- 用于寄存器与寄存器间的算术/逻辑运算
| 字段代号 | 名称 | 位长 |
|---|---|---|
op | 操作码,几乎恒为 000000 | 6 |
rs | 第一个源操作数寄存器 | 5 |
rt | 第二个源操作数寄存器 | 5 |
rd | 存放目的结果的寄存器 | 5 |
shamt | 位移量 | 5 |
funct | 功能码,用于区分什么运算 | 6 |
I-Type:op[6] rs[5] rt[5] immediate[16]
- 立即数运算:
addi/andi/ori rt rs imm - 访存:
lw/sw rt offset(rs) - 条件分支:
beq/bne rs rt offset
| 字段代号 | 名称 | 位长 |
|---|---|---|
op | 操作码 | 6 |
rs | 第一个源操作数寄存器 | 5 |
rt | 第二个源操作数寄存器 | 5 |
immediate | 立即数或者偏移地址 符号扩展: addi / lw / sw / beq零扩展: andi / ori | 16 |
J-Type:op target-address
- 跳转指令:
j/jal target
| 字段代号 | 名称 | 位长 |
|---|---|---|
op | 操作码 | 6 |
target-address | JumpAddr = [PC[31:28], target-address, 00]其中 PC 是当前指令地址 $+4$(下一条指令地址) | 26 |
4.1.2+4.1.3 操作码指令格式
定长操作码:最高位固定长度表示操作码,若有 $n$ 位,则最大能够表示 $2^n$ 条指令
$$\bigstar \mathbf{IMPORTANT}\bigstar$$ 扩展操作码:操作码的长度随地址码的减少而增加。
- 不允许短码是长码的前缀,因此短码编码完后必须留下其他前缀来扩展。
- 各指令的操作码一定不能重复。
- 对于频率较高的指令分配较短的操作码,对于频率较低的指令分配较长的操作码
指令格式设时,要注意指令字长应是字节的整数倍!
4.1.4 指令的操作类型
- 数据传送:
Mov, Load, Store - 算术和逻辑运算:
Add, Sub, Cmp, Mul, Div, Inc, Dec, And, Or, Not, Xor - 移位操作:算法移位、逻辑移位、循环移位
- 转移操作:
Jmp, Branch, Call, Ret, Trap - IO 操作
4.2 指令的寻址方式
常见寻址方式
4.2.1 指令寻址和数据寻址
形式地址 A:指令中的地址码字段
真实地址 EA:操作数在存储器中的真实地址。
指令寻址:寻找下一条要执行的指令地址
- 顺序寻址:根据
PC + 1得出下一条指令的地址。 - 跳跃寻址:由本条指令得出下一条指令地址的计算方式。
数据寻址:寻找本条指令的数据地址
- 常在指令字中设一个字段表示数据的寻址方式
4.2.2 常见的数据寻址方式
$$\bigstar \mathbf{IMPORTANT}\bigstar$$
| 寻址方式 | 解释 | 操作数/真实地址计算 | 优点 | 缺点 |
|---|---|---|---|---|
| 隐含寻址 | 在指令中隐含操作数的地址 如操作数是累加器 ACC 而不显式给出 | 指令短 | 1. 需要增加操作数 2. 需要隐含地址的硬件 | |
| 立即数寻址 | 地址字段是操作数本身,又称立即数 Immediate | $操作数 = A$ | 指令执行时间短,无需访问内存 | 操作数的大小受字段长度的限制 |
| 直接寻址 | 地址字段是真实地址 EA | $EA = A$ | 简单直接 | 寻址空间受地址字段长度的限制 |
| 间接寻址 | 指令的地址码 $A1$ 指向主存的地址,访存得到操作数的地址 $A2$,再次访存得到操作数 $Data$ 可以多次间接寻址 | $EA = (A)$ | 寻址空间大,灵活,便于编程 | 需要两次访存才能取到操作数,速度慢 |
| 寄存器寻址 | 操作数在寄存器中,所在的寄存器的编号放到指令当中 | $EA = R$ | 只需要很短的地址字段 无需访问内存,速度快 使用最多,提高性能 | 地址范围有限 |
| 寄存器间接寻址 | 指令的地址码 $R_n$ 指向第 $n$ 个寄存器的地址,访存得到操作数的地址 $A$,再次访存得到操作数 $Data$ | $EA = (R)$ | - 比存储器间接寻址少访问内存一次 - 寻址空间大,使用比较普遍 | 额外存储器访问 |
| 偏移寻址 | 指令的地址码 $R_b$ 指向第 $b$ 个寄存器的地址,访存得到地址 $N$,再加上立即数 $A$ 得到 $N+A$,再次访存得到操作数 $Data$ 分为PC相对寻址、基址寻址、变址寻址 | $EA = A + (R)$ | 灵活 | 复杂 |
| 堆栈寻址 | 堆栈是一个内存区域。 进程的区域中,栈区域从高到低地址扩展,堆区域(动态分配区)从低到高地址扩展。 堆栈指针是一个特殊寄存器,指向栈顶。 两个操作 PUSH/POP 会使指针减/加。 | $EA = SP$ | 指令短 | 应用有限 |

偏移寻址的三种类型: 依照寄存器类型的不同分为三类 $$\bigstar \mathbf{IMPORTANT}\bigstar$$ $\bigstar$ PC相对寻址:下一条指令的地址相对于该条指令的地址码的偏移量。立即数 $A$ 代表跳过了多少条指令,它是一个有符号数,补码表示。
- 起跳点是当前指令的下一条指令
- $A$ 一般(默认)代表跳过的字节数,也可代表跳过的指令数,一般每条指令有 2 字节。
- 因此目标地址就是 $PC + (1 + \Delta) \times bytes_per_instrc$ 或 $PC + (1 + \Delta)$
- 偏移量是一个有符号数,例如 8 位就是 $[-128, 127]$
常用于函数内部的分支、跳转指令
基址寻址:程序的头部地址放在基址寄存器当中,这个地址由操作系统确定,在程序执行过程中不会随意改变。
将文件基地址加上偏移量就得到相应函数的地址。
常用于函数之间的跳转指令。
变址寻址:数组头部地址放在变址寄存器当中,这个地址一般由用户设定,在程序执行过程中可变。
将数组基址加上偏移量就得到相应数组元素的地址。
常用于数组等顺序结构的访问。
4.3 *程序的机器级代码表示
常用汇编指令、过程调用、选择语句、循环语句
4.4 CISC 和 RISC 的基本概念
CISC、RISC $$\bigstar \mathbf{IMPORTANT}\bigstar$$
| 对比方面 | CISC | RISC |
|---|---|---|
| 设计思想 | 指令系统复杂,用复杂指令完成复杂功能 | 指令系统精简,用简单指令组合完成复杂功能 |
| 指令数量 | 指令多,通常 200 条以上 | 指令少 |
| 指令长度 | 不固定长度 | 固定长度 |
| 指令格式 / 寻址方式 | 格式多、寻址方式多 | 格式少、寻址方式少 |
| 是否允许指令直接访存 | 多数指令可直接访存 | 只有 Load / Store 指令访存 |
| 寄存器数量 | 通用寄存器较少 | 通用寄存器较多 |
| 指令执行周期 | 多数指令需要 多个时钟周期 | 大多数指令 1 个时钟周期完成 |
| 是否适合流水线 | 不利于流水线 | 天然适合流水线 |
| 控制器实现方式 | 微程序控制为主 | 硬布线控制为主 |
| 编译优化 | 不利于编译优化 | 非常利于编译优化 |
| 运算速度 | 相对较慢 | 相对较快 |
| 设计复杂度 | 设计复杂、研制周期长 | 设计简单、研制周期短 |
| 软件兼容性 | 兼容性好 | 兼容性较差 |
| 发展趋势 | 现代 CISC 融合 RISC 思想 | 被认为是未来处理器的发展方向 |