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] = $12

Entonces

PC = $1234

Importante

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