021. Lda indirecto y

Añadir LDA indexado indirecto ($B1, escrito `(d),Y`).

Lección 21 de 356 · tests/chapter_01_cpu/test_021_LDA_indirect_y.py

Archivos a actualizar

emulator/cpu/addressing_modes.py
emulator/cpu/opcodes.py

Ubicaciones

addressing_modes.indirect_y
opcodes import of indirect_y
opcodes.lda_indirect_y
opcodes.OPCODE_TABLE[$B1]

Por qué existe este paso

El Test 020 indexaba el puntero de página cero con X antes de desreferenciarlo. Este modo, en cambio, lee un puntero de página cero sin indexar y suma Y a la dirección base de 16 bits ensamblada, completando las dos formas indexadas indirectas de LDA.

Implementación de ejemplo completa

# emulator/cpu/addressing_modes.py
def indirect_y(cpu) -> int:
    pointer = cpu.fetch_byte()
    low = cpu.bus.read(pointer)
    high = cpu.bus.read((pointer + 1) & 0xFF)
    return (low | (high << 8)) + cpu.y


# emulator/cpu/opcodes.py
from emulator.cpu.addressing_modes import indirect_y


def lda_indirect_y(cpu) -> None:
    address = indirect_y(cpu)
    value = cpu.bus.read(address)
    lda(cpu, value)


OPCODE_TABLE = {
    # Preserve existing entries.
    0xB1: lda_indirect_y,
}

Invariantes importantes

  • se obtiene exactamente un byte de operando
  • la lectura del byte alto del puntero da la vuelta desde la página cero $FF a $00
  • Y se suma después de ensamblar el puntero en little-endian
  • el manejador lee la dirección final y delega en lda las actualizaciones de A y Z/N

Concepto erróneo habitual

(d),Y no suma Y al operando antes de leer el puntero; eso lo confundiría con el orden (d,X) del Test 020.

Fuera de alcance

  • STA y sus manejadores de opcode
  • penalizaciones de ciclos por cruce de página
  • una abstracción compartida para los dos modos indexados indirectos

Ejecutar esta lección

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