184. Instrucción jsr
añadir el comportamiento de JSR independiente del modo de direccionamiento.
Lección 184 de 356 · tests/chapter_01_cpu/test_184_instruction_jsr.py
En este paso, añade `emulator/cpu/instructions.py::jsr`:
Instrucción
JSR -> Jump to SubroutineObjetivo
implementar jsr(cpu, addr) en instructions.py.
Guía para el estudiante
JSR es como JMP, pero además guarda una dirección de retorno en la pila para que RTS pueda volver más tarde.
Detalles importantes
- La pila reside en la página $0100.
- S es solo el byte bajo de la dirección de la pila.
- Se apila primero el byte alto, luego el byte bajo.
- S se decrementa después de cada apilamiento.
- En el momento de jsr(cpu, addr), PC ya apunta a la siguiente instrucción.
- JSR apila PC - 1 porque RTS incrementa la dirección de retorno desapilada.
Forma de implementación de ejemplo
return_addr = (cpu.pc - 1) & 0xFFFF
high = (return_addr >> 8) & 0xFF
low = return_addr & 0xFF
cpu.bus.write(0x0100 | cpu.s, high)
cpu.s = (cpu.s - 1) & 0xFF
cpu.bus.write(0x0100 | cpu.s, low)
cpu.s = (cpu.s - 1) & 0xFF
cpu.pc = addr & 0xFFFFPor qué existe este paso
La decodificación del operando ya ha avanzado PC más allá de JSR, mientras que el protocolo de pila del 6502 almacena un valor menos que la dirección de continuación para un futuro RTS. Invariantes: las escrituras se producen primero el byte alto y luego el bajo en `$0100 | S`; S se decrementa y se envuelve tras cada escritura; PC y la dirección proporcionada son de 16 bits; las flags y el resto de registros se preservan. Concepto erróneo: apilar el PC actual, o apilar primero el byte bajo, produce un marco de retorno incompatible.
Fuera de alcance: no hay importación de opcode, manejador `jsr_absolute, ni entrada en la tabla para $20 hasta el paso 185. rts` no existe hasta el paso 186; explica la convención de PC-menos-uno, pero no debe implementarse aquí.
Ejecutar esta lección
uv run pytest tests/chapter_01_cpu/test_184_instruction_jsr.py -v