020. Lda indirect x

Добавить LDA с индексно-косвенной адресацией ($A1, записывается как `(d,X)`).

Урок 20 из 356 · tests/chapter_01_cpu/test_020_LDA_indirect_x.py

Файлы для обновления

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

Расположения

addressing_modes.indirect_x
opcodes.lda_indirect_x
opcodes.OPCODE_TABLE[$A1]

Почему этот шаг важен

Индексно-косвенная адресация использует операнд плюс X для выбора двухбайтового указателя в zero page. Затем этот указатель даёт итоговый 16-битный адрес значения LDA.

Полная пример-реализация

# emulator/cpu/addressing_modes.py
def indirect_x(cpu) -> int:
    operand = cpu.fetch_byte()
    pointer = (operand + cpu.x) & 0xFF

    low = cpu.bus.read(pointer)
    high = cpu.bus.read((pointer + 1) & 0xFF)

    return low | (high << 8)


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


def lda_indirect_x(cpu) -> None:
    address = indirect_x(cpu)
    lda(cpu, cpu.bus.read(address))


OPCODE_TABLE = {
    # Preserve existing entries.
    0xA1: lda_indirect_x,
}

Временная последовательность адресации для A1 20 при X=$04:

fetch operand $20
    -> pointer location $24
    -> read low byte from $0024
    -> read high byte from $0025
    -> assemble final address
    -> read value for LDA

Важные инварианты

  • X прибавляется до чтения указателя
  • выбор указателя переносится в пределах zero page
  • чтение старшего байта из указателя $FF переносится на $00

Распространённое заблуждение

Не прибавляйте X к итоговому 16-битному адресу. Это другой механизм адресации; (d,X) индексирует позицию указателя в zero page.

Вне рамок

  • indirect,Y, введённая в тесте 021
  • штрафы циклов при переходе через страницу
  • особое поведение косвенной адресации у JMP

Запустить этот урок

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