Appearance
题目
哪些指令可能不改变程序下一条指令的地址?( )
Ⅰ. 条件转移
Ⅱ. 过程调用
Ⅲ. 陷入指令
Ⅳ. 返回
错因
A
把"过程调用"和"条件转移"归为一类——可能因为两者都是"看情况跳转"。但过程调用是无条件跳转:CALL 指令一旦执行必然跳到子程序入口,没有"不跳"的分支,所以 II 一定会让"程序原本的下一条"被打断。条件转移才有"条件不满足→顺序执行"这条不跳分支。
C
误以为 II 过程调用和 III 陷入指令"可能不改变"——可能把"过程调用是显式的、看得见目标地址"误读成"程序员可控所以不会跳"。其实"显式 vs 隐式"和"是否跳转"是两件事:CALL 必跳到子程序入口,TRAP 必跳到陷入处理程序,两者都强制改变了主程序原定的执行流。
D
II 过程调用必然跳转(同 A),不能入选。可能是把 II 和 IV 当成"一对"——CALL 跳出去、RET 跳回来,配套出现就以为它们性质相同。事实上 IV 返回的特殊性恰恰来自"它把 PC 恢复到主程序原本要执行的下一条",这才是它"可能不改变程序原本下一条"的关键;II 没这种性质。
总解析
关键概念辨析——题目问的是"程序下一条指令的地址"。这里的"程序"应理解为主程序逻辑流,而不是单条指令的 PC+1。判据:执行该指令后,主程序原本约定要执行的下一条指令是否被打断 / 替换。
逐项判断:
| 编号 | 指令 | 执行行为 | 主程序原本的下一条还会被执行吗? |
|---|---|---|---|
| Ⅰ | 条件转移 | 条件成立 → 跳转;条件不成立 → 顺序执行 PC+1 | 可能不变(条件不成立时) |
| Ⅱ | 过程调用 CALL | 必然跳到子程序入口,主程序流被打断 | 改变 |
| Ⅲ | 陷入指令 TRAP | 必然进入陷入处理程序(异常入口) | 改变 |
| Ⅳ | 返回 RET | 弹出栈顶 PC = 原 CALL 后的那条,正是主程序原本要执行的下一条 | 不变 |
为什么 IV 返回算"不改变":
CALL+RET 是配对操作。把 CALL 之前的"主程序"看成一条单线程的指令流:
| 时刻 | 主程序视角的"应该执行的下一条" |
|---|---|
| 进入 CALL 之前 | 主程序里 CALL 之后那条指令 |
| 进入子程序、执行 RET 时 | 同上(栈中保存的就是这个地址) |
| RET 执行后 | PC 指向"主程序里 CALL 之后那条" ✓ |
也就是说,从主程序的视角,CALL+子程序+RET 这一整段执行下来,主程序的执行序列没有被打断——RET 恰好把控制权送回了"主程序原本要执行的下一条"。这是 IV 区别于 II、III 的关键:II 把控制权送往别处(子程序),III 把控制权送往陷入处理程序,只有 IV 把控制权"还原"。
对比 I 和 IV 的"不改变"含义:
- I 条件转移可能不改变:分两种情况,条件不满足时不跳转
- IV 返回总是不改变主程序流:从主程序视角看是恢复,不是打断
题目用"可能不改变"涵盖这两种情况:I 是"有时不改变",IV 是"从主程序视角不改变"——两者都符合"程序原本下一条指令地址未被打断"。
最终答案是 B(Ⅰ、Ⅳ)。
易错点:
- 这道题的"程序下一条指令的地址"指的是程序逻辑流上的下一条,不是 RET 这条单独指令的 PC+1
- 过程调用 II 是无条件的,不要因"看得见跳到哪里"而以为可以"不跳"
- 陷入指令 III 与中断处理同质,必然进入异常处理程序,没有"不进入"的分支