053. Инструкция adc

Добавить инструкцию ADC, не зависящую от режима адресации.

Урок 53 из 356 · tests/chapter_01_cpu/test_053_instruction_adc.py

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

emulator/cpu/instructions.py

Символ для создания

instructions.adc(cpu, value)

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

ADC — это арифметическое поведение, а не декодирование операнда. Она принимает значение, уже полученное обработчиком опкода, складывает его с A и входящим переносом Carry, усекает результат до одного байта и обновляет C, Z, N и V через FlagsHandler из теста 052.

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

# emulator/cpu/instructions.py
def adc(cpu, value: int):
    carry = int(cpu.flags.get_carry_flag())
    old_a = cpu.a
    total = old_a + value + carry
    result = total & 0xFF

    cpu.flags.set_carry_flag(total > 0xFF)
    cpu.flags.set_zero_flag(result == 0)
    cpu.flags.set_negative_flag((result & 0x80) != 0)
    overflow = (result ^ old_a) & (result ^ value) & 0x80
    cpu.flags.set_overflow_flag(overflow != 0)
    cpu.a = result

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

  • входящий Carry считывается до изменения каких-либо флагов
  • A хранит только младшие восемь бит полной суммы
  • Carry сообщает о беззнаковом переполнении; Overflow сообщает о знаковом переполнении
  • Zero и Negative вычисляются из усечённого результата
  • флаги, не названные выше, и регистры X/Y остаются без изменений

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

Carry и Overflow не взаимозаменяемы. Carry получается из 8-го бита беззнаковой суммы, тогда как Overflow возникает, когда операнды с одинаковым знаком дают результат с противоположным знаком.

Вне рамок задачи

  • все обработчики режимов адресации ADC и записи в таблице опкодов
  • SBC и арифметика в десятичном режиме
  • учёт циклов

Справочные материалы

https://www.nesdev.org/wiki/Instruction_reference#ADC

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

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