188. Manejador de flags de interrupción y de break
añadir los ayudantes para las flags I, B y el bit no usado.
Lección 188 de 356 · tests/chapter_01_cpu/test_188_flags_handler_interrupt_and_break_flags.py
En este paso, define Break como el bit 4 y el bit no usado del estado apilado como el bit 5. Añade a `emulator/cpu/flags_handler.py`:
INTERRUPT_FLAG = 1 << 2
B_FLAG = 1 << 4
ONE_FLAG = 1 << 5
def set_interrupt_disable_flag(self, enabled: bool):
if enabled:
self.cpu.p |= INTERRUPT_FLAG
else:
self.cpu.p &= ~INTERRUPT_FLAG
def set_break_flag(self, enabled: bool):
if enabled:
self.cpu.p |= B_FLAG
else:
self.cpu.p &= ~B_FLAG
def set_one_flag(self, enabled: bool):
if enabled:
self.cpu.p |= ONE_FLAG
else:
self.cpu.p &= ~ONE_FLAG
def get_interrupt_disable_flag(self) -> bool:
return bool(self.cpu.p & INTERRUPT_FLAG)
def get_break_flag(self) -> bool:
return bool(self.cpu.p & B_FLAG)
def get_one_flag(self) -> bool:
return bool(self.cpu.p & ONE_FLAG)Por qué existe este paso
Nos estamos preparando para implementar BRK.
BRK es una instrucción de interrupción por software. Para implementarla con claridad, la CPU necesita ayudantes para dos flags de estado:
I flag -> Interrupt Disable, bit 2
B flag -> Break, bit 4
ONE flag -> unused/status bit 5 used in pushed status bytesBRK las necesitará porque
- activa la flag de Interrupt Disable después de entrar en el manejador de interrupción
- apila un byte de estado con la flag de Break activada
Objetivo de diseño
Mantener la manipulación de bits dentro de FlagsHandler en lugar de repartir operaciones directas sobre los bits de cpu.p por todo el código de las instrucciones.
Terminología importante
Interrupt Disable flag:
When set, maskable IRQ interrupts are disabled.
Break flag:
Used to mark that the pushed status byte came from BRK.Error común
No confundas el opcode BRK con la flag Break.
BRK opcode: 0x00, the instruction byte in memory
B flag: bit 4 inside the status byte pushed to the stack
ONE flag: bit 5, usually set in pushed status bytesJustificación: los métodos de asignación con nombre centralizan operaciones independientes de lectura-modificación-escritura sobre P, y los métodos de lectura exponen valores booleanos. Invariantes: cada método de asignación cambia solo su bit; I, B, ONE y el resto de flags existentes permanecen independientes. Concepto erróneo: B y el bit siempre a uno del estado apilado no son el mismo bit, y el opcode $00 tampoco lo es.
Fuera de alcance: este paso no implementa BRK ni decide cuándo se activan los bits; eso son los pasos 189-190. RTI/PHP/PLP, el comportamiento de NMI, y los ayudantes de pila de la CPU quedan para trabajo posterior.
Ejecutar esta lección
uv run pytest tests/chapter_01_cpu/test_188_flags_handler_interrupt_and_break_flags.py -v