021. Lda indirect y

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

Урок 21 из 356 · tests/chapter_01_cpu/test_021_LDA_indirect_y.py

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

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

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

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

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

Тест 020 индексировал указатель нулевой страницы регистром X перед разыменованием. Этот режим вместо этого читает неиндексированный указатель нулевой страницы и прибавляет Y к собранному 16-битному базовому адресу, завершая две косвенно-индексные формы LDA.

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

# 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,
}

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

  • выбирается ровно один байт операнда
  • чтение старшего байта указателя циклически переходит с $FF на $00 в пределах нулевой страницы
  • Y прибавляется после сборки указателя в формате little-endian
  • обработчик читает итоговый адрес и делегирует обновление A и флагов Z/N инструкции lda

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

(d),Y не прибавляет Y к операнду перед чтением указателя; это перепутало бы её с порядком (d,X) из Теста 020.

Вне рамок

  • STA и её обработчики опкодов
  • штрафы циклов за пересечение страницы
  • общая абстракция для двух косвенно-индексных режимов

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

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