183. JMP 间接寻址

接入 JMP 间接寻址操作码 $6C。

183 / 356 · tests/chapter_01_cpu/test_183_JMP_indirect.py

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

from emulator.cpu.instructions import jmp
from emulator.cpu.addressing_modes import indirect

def jmp_indirect(cpu: CPU):
    addr = indirect(cpu)
    jmp(cpu, addr)

OPCODE_TABLE = {
    # existing entries...
    0x6C: jmp_indirect,
}

操作码

0x6C -> JMP ($hhhh)

目标

创建 jmp_indirect(cpu),使用 indirect(cpu),然后调用 jmp(cpu, addr)。

学习指引

JMP 间接寻址把操作数当作指向目标地址的指针来使用。

示例

6C 00 02 means JMP ($0200)

如果

memory[$0200] = $34
memory[$0201] = $12

那么

PC = $1234

重要提示

indirect(cpu) 已经返回了最终的目标地址。该操作码的处理函数不能再对这个返回的地址进行内存读取。

NES/6502 的 bug

如果指针以 $FF 结尾,高字节会在同一页内发生回绕:

JMP ($02FF) reads high byte from $0200, not $0300.

本步骤存在的原因

`addressing_modes.indirect 消费指针操作数,按照 6502 的页边界行为进行处理,并返回最终目标地址;随后由 jmp 将其赋值。不变量:该处理函数不会执行额外的目标地址读取,保持标志位/寄存器/栈/内存不变,并且只映射 $6C。常见误解:indirect` 返回的值并不是另一个指针。

本步骤范围之外:实现或修改 `addressing_modes.indirect` 属于第 180 步。JSR 从第 184 步开始;RTS 与中断属于后续步骤。

运行本课

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