011. Lda absolute
Добавить LDA с абсолютной адресацией ($AD).
Урок 11 из 356 · tests/chapter_01_cpu/test_011_LDA_absolute.py
Файл для обновления
emulator/cpu/cpu.pyРасположение
CPU.step, new $AD branchПочему этот шаг важен
Непосредственная LDA загружает свой операнд напрямую. Абсолютная же LDA считывает двухбайтовый адрес в порядке little-endian, читает значение, хранящееся по этому адресу, и применяет то же поведение флагов Zero и Negative, изученное в тесте 010.
Полный пример реализации
ZERO_FLAG = 1 << 1
NEGATIVE_FLAG = 1 << 7
class CPU:
def step(self) -> None:
opcode = self.fetch_byte()
if opcode == 0xA9:
self.a = self.fetch_byte()
if self.a == 0:
self.p |= ZERO_FLAG
else:
self.p &= ~ZERO_FLAG
if self.a & NEGATIVE_FLAG:
self.p |= NEGATIVE_FLAG
else:
self.p &= ~NEGATIVE_FLAG
return
if opcode == 0xAD:
address = self.fetch_word()
self.a = self.bus.read(address)
# In this step, flag behavior is intentionally
# duplicated before Test 012 extracts the common helper.
if self.a == 0:
self.p |= ZERO_FLAG
else:
self.p &= ~ZERO_FLAG
if self.a & NEGATIVE_FLAG:
self.p |= NEGATIVE_FLAG
else:
self.p &= ~NEGATIVE_FLAG
return
raise NotImplementedError(
f"Opcode {opcode:02X} not implemented"
)Важные инварианты
- $AD занимает три байта инструкции: опкод, младший байт адреса, старший байт адреса
- чтение с шины использует собранный 16-битный адрес
- и установка, и сброс Z/N работают в последовательных инструкциях
Распространённое заблуждение
Байты 34 12 — это не значение $1234, загружаемое в A. Они образуют адрес $1234; затем LDA загружает байт, хранящийся по этому адресу.
Вне рамок
- вынесение общей логики флагов в отдельную функцию
- вынесение функций адресации и инструкций
- другие режимы адресации LDA
Запустить этот урок
uv run pytest tests/chapter_01_cpu/test_011_LDA_absolute.py -v