188. Обработчик флагов: флаги Interrupt и Break
добавить вспомогательные функции для флагов I, B и неиспользуемого бита.
Урок 188 из 356 · tests/chapter_01_cpu/test_188_flags_handler_interrupt_and_break_flags.py
На этом шаге определите Break как бит 4 и неиспользуемый бит записываемого статуса как бит 5. Добавьте в `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)Зачем нужен этот шаг
Мы готовимся к реализации BRK.
BRK — это инструкция программного прерывания. Для её чёткой реализации CPU нужны вспомогательные функции для двух флагов статуса:
I flag -> Interrupt Disable, bit 2
B flag -> Break, bit 4
ONE flag -> unused/status bit 5 used in pushed status bytesBRK потребует их, потому что
- она устанавливает флаг Interrupt Disable после входа в обработчик прерывания
- она записывает байт статуса с установленным флагом Break
Цель проектирования
Сосредоточить битовые манипуляции внутри FlagsHandler, а не разбрасывать сырые побитовые операции с cpu.p по коду инструкций.
Важная терминология
Interrupt Disable flag:
When set, maskable IRQ interrupts are disabled.
Break flag:
Used to mark that the pushed status byte came from BRK.Частая ошибка
Не путайте опкод BRK с флагом 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 bytesОбоснование: именованные сеттеры централизуют независимые операции чтения-изменения-записи над P, а геттеры предоставляют булевы значения. Инварианты: каждый сеттер изменяет только свой бит; I, B, ONE и все существующие флаги остаются независимыми. Заблуждение: B и всегда единичный бит записываемого статуса — это не один и тот же бит, и опкод $00 тоже не является ни одним из них.
За рамками шага: этот шаг не реализует BRK и не определяет, когда биты устанавливаются; это шаги 189–190. RTI/PHP/PLP, поведение NMI и вспомогательные функции стека CPU относятся к последующим шагам.
Запустить этот урок
uv run pytest tests/chapter_01_cpu/test_188_flags_handler_interrupt_and_break_flags.py -v