191. 指令 rti

实现 RTI 行为。

191 / 356 · tests/chapter_01_cpu/test_191_instruction_rti.py

在本步骤中,只修改 `emulator/cpu/instructions.py,添加 rti(cpu)`。前置条件:第 188 步已引入所需的中断和 Break 标志相关 API。

本步骤存在的原因

中断进入时会在接下来的三个栈槽中依次保存 status、返回 PC 低字节和返回 PC 高字节。RTI 必须按这个后进先出的顺序取出这些字节,并恢复出精确的 PC;与 RTS 不同,它不能再额外加一。

建议实现

cpu.s = (cpu.s + 1) & 0xFF
flags = cpu.bus.read(0x0100 | cpu.s)
cpu.p = flags & 0b1100_1111

cpu.s = (cpu.s + 1) & 0xFF
low = cpu.bus.read(0x0100 | cpu.s)

cpu.s = (cpu.s + 1) & 0xFF
high = cpu.bus.read(0x0100 | cpu.s)

cpu.pc = (high << 8) | low

把这些语句放入 `def rti(cpu: CPU)` 中。

不变量:每次读取前先递增 8 位的 S;只读取栈页 $0100;替换 P 时要先屏蔽第 4 位和第 5 位;先取低字节后取高字节;S 共递增三次;恢复出的 PC 不再递增。

常见误解:RTI 并不是用于中断的 RTS。如果照搬 RTS 最后的 `+ 1`,会返回到错误的指令位置。

范围之外:在 $40 处导入/注册操作码属于第 192 步。NMI 行为属于之后的步骤,这里不得添加。

运行本课

uv run pytest tests/chapter_01_cpu/test_191_instruction_rti.py -v