指令的操作类型

前三节讲的是指令怎么编码,这一节讲编码出来的那些操作码分别代表什么。

内容本身是一张分类表,容易读成背诵材料。但它有一个更有用的读法:这张表就是 CPU 数据通路必须提供的功能清单。 每一类指令都对应通路上一组必须存在的部件和连线——这个反推能力是第 5 章数据通路题的起手式,所以本节最后会把这层对应关系摆出来。

机制

五大类

类别典型指令干什么要求通路提供什么
数据传送MOV LOAD STORE PUSH POP把数据从一处搬到另一处,内容不变寄存器↔寄存器、寄存器↔主存的通路,MAR/MDR
算术逻辑运算ADD SUB MUL DIV INC CMP AND OR NOT XOR TEST产生新值并置标志位ALU + 标志位寄存器 PSW
移位操作算术移位、逻辑移位、循环移位按位挪动移位器(可独立、可集成在 ALU 内)
转移操作JMP Jcc CALL RET TRAP/INT IRET改变指令执行顺序写 PC 的通路 + 读 PSW 的通路 + 栈操作
输入输出IN OUT与外设接口交换数据通向 I/O 端口的通路(仅独立编址)

数据传送类:搬运,不加工

传送指令的定义性特征是”内容不变”,所以它有一条重要的副作用性质:一般不影响标志位。x86 的 MOV 执行完,ZF、CF 全部保持原值——这是写指令序列时的关键依据,因为它意味着可以在 CMP 和 Jcc 之间插入 MOV 而不破坏条件。(同样性质的还有 LEA,见 4.3.1。)

LOAD / STORE 这对名字专指主存与寄存器之间的传送。在 RISC 里它们是唯一能访存的指令,别的指令一律只碰寄存器——这就是 Load/Store 结构,见 4.4.2。CISC 里没有这个限制,ADD 的操作数可以直接是主存单元。

PUSH / POP 隐含使用栈指针 SP,每次自动修改 SP。它们是零地址或一地址指令,是堆栈寻址的直接体现。

算术逻辑类:唯一会置标志位的主力

标志位(PSW 中的 OF、SF、ZF、CF)几乎全部由这一类指令产生,然后被转移类指令消费。“产生标志位”和”消费标志位”分属两类指令,中间靠 PSW 传递——这是所有条件分支的工作原理,4.3.2 全靠它。

两条特殊指令必须单列:

  • CMP A, B:做 ,只置标志位,不保存差值
  • TEST A, B:做 ,只置标志位,不保存结果

它们是”只要副作用、不要结果”的运算,专门为紧接其后的条件转移服务。

移位类:不需要 ALU 参与

三类移位(逻辑 / 算术 / 循环)的区分判据、以及移位到底由谁实现,已在 2.2.2 定点数的移位运算完整讨论。这里只重复结论:三类移位都不需要 ALU 做加减,移位部件既可以集成在 ALU 内部由 ALUop 选择,也可以独立成移位器由 SRop 控制,两种实现都真实存在。

转移类:唯一能写 PC 的指令

这一类指令的共同本质是”给 PC 装一个新值”,区别只在装什么值和要不要先把旧值存起来:

指令新 PC 从哪来保存返回地址?保存到哪
JMP 无条件转移指令的地址字段算出的 EA❌——
Jcc 条件转移同上,但先查 PSW 决定转不转❌——
CALL 子程序调用子程序入口✅栈(或专用寄存器)
RET 返回从栈弹出————
TRAP / INT 陷阱(软中断)中断向量表查出✅栈(同时保存 PSW)
IRET 中断返回从栈弹出——同时恢复 PSW

三条边界,每一条都是高频判断题:

  1. CALL 和 JMP 的唯一区别是保不保存返回地址。 转移的动作两者完全相同。
  2. TRAP/INT 比 CALL 多保存一个 PSW,并且会切换特权级。 这是它成为用户态主动进入内核态的唯一途径的原因——见 OS 1.3.3 系统调用。所以 RET 和 IRET 不能互换。
  3. TRAP 是指令、是同步的、是程序自愿的;外部中断是事件、是异步的、与当前指令无关。 两者的完整对照在 5.6 异常和中断(本地资料)。

输入输出类:存在与否取决于编址方式

IN / OUT 这类专用 I/O 指令,只在”I/O 独立编址”的机器上存在。

  • 独立编址:I/O 端口有自己的地址空间,必须用专用 I/O 指令,指令里的地址是端口号(x86 就是这种)
  • 统一编址(存储器映射 I/O):端口占用主存地址空间的一段,普通的访存指令就能读写外设,ISA 里根本不需要 I/O 指令(MIPS 就是这种)

“没有专用 I/O 指令”不等于”不能做 I/O”,这是判断题的常见反向陷阱。完整讨论见 7.2.4 I/O 端口及其编址。

关联对照:把指令类型表读成数据通路的功能清单

第 5 章的数据通路题,起手式是从指令类型反推通路上必须有什么。这张对应表现在建立,到 5.2 就是现成的:

有这类指令通路上必须有
任何指令PC、IR、取指通路、PC+1 的加法器
LOAD/STOREMAR、MDR、地址总线与数据总线的连接
算术逻辑类ALU、两个输入端的多路选择器、PSW
移位类移位器(或 ALU 内的移位功能)
JccPSW 到控制器的通路 + 写 PC 的通路
CALL/RETSP、PC 到 MDR 的通路(把返回地址写进栈)
TRAP/中断PSW 的保存/恢复通路、中断向量的地址来源

反过来用同样成立:给一张数据通路图,图上有什么部件,就决定了它能支持哪类指令。用户的 5.1 那道”这张图能不能执行 CALL”的题,判据就是有没有一条从 PC 到 MDR 的路。

边界

“数据传送”不改变数据本身,但可能改变数据的位置和可见性。 STORE 之后主存变了、Cache 可能变脏(见 3.5.5);PUSH 之后 SP 变了。“不改变内容”说的是被搬运的那个值,不是说没有副作用。

CMP 不是”比较大小并返回真假”。 它做的是减法并置标志位,大小关系是靠随后的 Jcc 读标志位组合判断出来的。带符号数看 SF、OF、ZF,无符号数看 CF、ZF——同一条 CMP 后面跟不同的 Jcc,判断的是不同的序关系,这一条在 4.3.2展开。

条件转移指令读标志位,但不一定由紧邻的上一条指令产生。 只要中间的指令不影响相关标志位(比如 MOV、LEA),CMP 和 Jcc 之间可以隔着别的指令。编译器优化经常这么做。

指令类型的多少是 CISC/RISC 的一条表面差别,不是本质差别。 本质差别在指令的复杂度和访存方式(见 4.4.3)。RISC 的指令条数其实不一定少,“精简”精简的是每条指令的功能。

统考不要求记忆具体某款机器的助记符表。 要求的是:给一条指令,判断它属于哪类、会不会访存、会不会改标志位、会不会改 PC。 这四问就是本节的全部考法。

对照速查

指令改标志位?访存?改 PC?
MOV 寄存器间❌❌❌
LOAD / STORE❌✅❌
PUSH / POP❌✅❌(改 SP)
ADD / SUB / AND✅看寻址方式❌
CMP / TEST✅ 只改标志位看寻址方式❌
移位类✅(CF 常被改)看寻址方式❌
JMP❌看寻址方式✅
Jcc❌(读标志位)看寻址方式✅(条件成立时)
CALL❌✅(压返回地址)✅
RET❌✅(弹返回地址)✅
TRAP / INT✅(保存并切换 PSW)✅✅
IRET✅(恢复 PSW)✅✅
判断对错
CALL 与 JMP 的区别是保存返回地址✅
RET 与 IRET 可以互换❌(IRET 还要恢复 PSW 与特权级)
CMP 会把差值写回目的操作数❌
MOV 会影响标志位❌
没有 IN/OUT 指令的机器不能做 I/O❌(统一编址用访存指令)
TRAP 是异步事件❌(是指令,同步、自愿)
RISC 的指令条数一定比 CISC 少❌(精简的是每条指令的功能)

考点

  • 五大类:数据传送、算术逻辑、移位、转移、输入输出
  • 传送类不改标志位;CMP/TEST 只改标志位不写结果
  • 算逻类产生标志位,转移类消费标志位,中间靠 PSW 传递
  • 转移类的本质是写 PC;CALL 比 JMP 多存返回地址,TRAP 比 CALL 多存 PSW 并切特权级
  • TRAP 是用户态主动进内核态的唯一途径;RET 与 IRET 不可互换
  • 专用 I/O 指令只在独立编址下存在,统一编址用普通访存指令
  • 指令类型表 ⇔ 数据通路功能清单,是第 5 章数据通路题的起手式

链接