102. Instruction rol
реализовать ROL для памяти.
Урок 102 из 356 · tests/chapter_01_cpu/test_102_instruction_rol.py
На этом шаге добавьте только примитив ROL для памяти. Поведение для аккумулятора появится в уроке 103, а раскрытие через опкоды относится к урокам 104-108.
Полный пример реализации в производственном месте
`emulator/cpu/instructions.py::rol`::
def rol(cpu: CPU, addr: int):
value = cpu.bus.read(addr)
old_carry = int(cpu.flags.get_carry_flag())
result = (value << 1) | old_carry
result_8 = result & 0xFF
# Set flags
cpu.flags.set_carry_flag((value & 0b1000_0000) != 0)
cpu.flags.set_zero_flag(result_8 == 0)
cpu.flags.set_negative_flag((result_8 & 0b1000_0000) != 0)
cpu.bus.write(addr, result_8)Зачем нужен этот шаг
Один независимый от режима адресации примитив чтения/модификации/записи позволяет каждому опкоду, работающему с памятью, повторно использовать идентичную семантику вращения и флагов.
Инварианты: значение Carry фиксируется до изменения флагов; старый Carry попадает в бит 0, старый бит 7 становится Carry, сохранённый результат маскируется до восьми бит, а Zero и Negative выводятся из этого сохранённого результата. Читается и записывается ровно один целевой адрес; A не изменяется.
Заблуждение: ROL — это не ASL. Он вставляет старый Carry, а не всегда вставляет ноль, и Carry должен браться из исходного значения, а не из `result_8`.
Вне рамок: ROL для аккумулятора — урок 103, адаптеры опкодов/адресации — 104-108, а ROR начинается с урока 109; поведение шины на уровне тактов появится позже.
Запустить этот урок
uv run pytest tests/chapter_01_cpu/test_102_instruction_rol.py -v