185. JSR 绝对寻址

接入 JSR 绝对寻址操作码 $20。

185 / 356 · tests/chapter_01_cpu/test_185_JSR_absolute.py

前置条件:第 184 步已添加 `jsr。在本步骤中,向 emulator/cpu/opcodes.py` 添加以下改动:

from emulator.cpu.instructions import jsr
from emulator.cpu.addressing_modes import absolute

def jsr_absolute(cpu: CPU):
    addr = absolute(cpu)
    jsr(cpu, addr)

OPCODE_TABLE = {
    # existing entries...
    0x20: jsr_absolute,
}

操作码

0x20 -> JSR $hhhh

目标

创建 jsr_absolute(cpu),使用 absolute(cpu),然后调用 jsr(cpu, addr)。

学习指引

JSR 绝对寻址使用一个 16 位小端序操作数作为子程序地址。

示例

20 34 12 -> JSR $1234

执行步骤

1. CPU.step() fetches opcode 0x20.
2. absolute(cpu) fetches operand bytes 34 12 and returns $1234.
3. PC now points to the next instruction, $8003 in these tests.
4. jsr(cpu, $1234) pushes return address $8002.
5. PC becomes $1234.

常见错误

不要调用 jmp(cpu, addr)。JSR 必须先压入返回地址。

本步骤存在的原因

`absolute 消费两字节的目标地址,使 PC 停留在下一条指令处,从而让 jsr` 能够压入 PC 减一后的值并跳转。不变量:该步骤消费操作码加操作数,先压入高字节再压入低字节,S 递减两次,PC 变为目标地址,并保持状态不变。常见误解:与 JMP 共用同一种寻址方式,并不意味着 JSR 只是一次普通跳转。

本步骤范围之外:`rts` 与操作码 $60 属于第 186-187 步。BRK、RTI 以及后续通用的栈辅助函数不属于本次改动。

运行本课

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