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