183. Jmp indirect
подключить опкод JMP indirect $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 indirect использует операнд как указатель на целевой адрес.
Пример
6C 00 02 means JMP ($0200)Если
memory[$0200] = $34
memory[$0201] = $12Тогда
PC = $1234Важно
indirect(cpu) уже возвращает конечный целевой адрес. Обработчик опкода не должен повторно читать память по этому возвращённому адресу.
Ошибка NES/6502
Если указатель заканчивается на $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