062. Instruction sbc
Añadir la instrucción central SBC.
Lección 62 de 356 · tests/chapter_01_cpu/test_062_instruction_sbc.py
Archivo a actualizar
emulator/cpu/instructions.pySímbolo a añadir
instructions.sbcPor qué existe este paso
SBC introduce la resta como instrucción central basada en valores antes de conectar ningún opcode. En el 6502, la flag de Carry significa "sin préstamo", por lo que la resta puede implementarse como la suma del complemento de ocho bits del operando más Carry.
Implementación de ejemplo completa
# emulator/cpu/instructions.py
def sbc(cpu: CPU, value: int):
carry = int(cpu.flags.get_carry_flag())
a = cpu.a
value_inverted = (~value) & 0xFF
result = a + value_inverted + carry
result_8 = result & 0xFF
cpu.flags.set_carry_flag(result > 0xFF)
cpu.flags.set_zero_flag(result_8 == 0)
cpu.flags.set_negative_flag((result_8 & 0x80) != 0)
overflow = ((result_8 ^ a) & (result_8 ^ value_inverted)) & 0x80
cpu.flags.set_overflow_flag(overflow != 0)
cpu.a = result_8Invariantes importantes
- con Carry activado se resta solo
value; con Carry desactivado se resta uno adicional - A se reduce al resultado final de ocho bits
- Carry se activa exactamente cuando no se produce préstamo
- Zero y Negative siguen el resultado final de ocho bits
- Overflow sigue la resta con signo, no el préstamo sin signo
Concepto erróneo común
El ~value sin procesar de Python es negativo porque los enteros no tienen límite. Enmascáralo con & 0xFF antes de sumar; tampoco trates Carry como un bit de préstamo convencional.
Fuera de alcance
- todos los manejadores de opcode de SBC y las entradas de la tabla de opcodes
- obtener operandos o seleccionar modos de direccionamiento dentro de
sbc - la aritmética en modo decimal y la temporización de ciclos
Referencia
https://www.nesdev.org/wiki/Instruction_reference#SBC
Ejecutar esta lección
uv run pytest tests/chapter_01_cpu/test_062_instruction_sbc.py -v