053. 指令 adc

添加与寻址方式无关的 ADC 指令。

53 / 356 · tests/chapter_01_cpu/test_053_instruction_adc.py

要更新的文件

emulator/cpu/instructions.py

要创建的符号

instructions.adc(cpu, value)

为什么需要这一步

ADC 是算术行为,而不是操作数解码。它接收已由操作码处理函数解析好的值,将其连同传入的 Carry 一起加到 A 上,把结果截断为一个字节,并通过测试 052 的 FlagsHandler 更新 C、Z、N 和 V。

完整示例实现

# 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