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