183. Jmp indirecto
conectar el opcode JMP indirecto $6C.
Lección 183 de 356 · tests/chapter_01_cpu/test_183_JMP_indirect.py
Requisitos previos: el paso 180 añadió `indirect y el paso 181 añadió jmp. En este paso, añade estos cambios a 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,
}Opcode
0x6C -> JMP ($hhhh)Objetivo
crear jmp_indirect(cpu), usar indirect(cpu), y luego jmp(cpu, addr).
Guía para el estudiante
JMP indirecto usa el operando como un puntero a la dirección destino.
Ejemplo
6C 00 02 means JMP ($0200)Si
memory[$0200] = $34
memory[$0201] = $12Entonces
PC = $1234Importante
indirect(cpu) ya devuelve la dirección destino final. El manejador del opcode no debe volver a leer memoria en esa dirección devuelta.
Bug del NES/6502
Si el puntero termina en $FF, el byte alto se envuelve dentro de la misma página:
JMP ($02FF) reads high byte from $0200, not $0300.Por qué existe este paso
`addressing_modes.indirect consume el operando del puntero, aplica el comportamiento de límite de página del 6502, y devuelve el destino final; jmp lo asigna a continuación. Invariantes: el manejador no realiza ninguna lectura adicional del destino, se preservan flags/registros/pila/memoria, y solo se mapea $6C. Concepto erróneo: el valor devuelto por indirect` no es otro puntero.
Fuera de alcance: implementar o cambiar `addressing_modes.indirect` corresponde al paso 180. JSR empieza en el paso 184; RTS y las interrupciones son pasos posteriores.
Ejecutar esta lección
uv run pytest tests/chapter_01_cpu/test_183_JMP_indirect.py -v