116. Instruction and a

implement addressing-independent AND behavior.

Lesson 116 of 356 · tests/chapter_01_cpu/test_116_instruction_and_a.py

In this step, add only `and_a to emulator/cpu/instructions.py`. Opcode imports and AND addressing modes follow in lessons 117-124.

Why this step exists

Defining AND as a value-oriented primitive keeps accumulator and flag semantics in one place so every addressing-mode handler can reuse them consistently.

Suggested implementation

def and_a(cpu: CPU, value: int):
    result_8 = (cpu.a & value) & 0xFF

    # Flags:
    cpu.flags.set_zero_flag(result_8 == 0)
    cpu.flags.set_negative_flag((result_8 & 0b1000_0000) != 0)

    cpu.a = result_8

The value-oriented signature keeps instruction semantics separate from address decoding. The result is constrained to eight bits, stored in A, Zero reflects equality to zero, and Negative reflects result bit 7. Carry, Overflow, memory, X, Y, and PC are invariant because this function never touches them.

Misconception: `value is not an address to read through cpu.bus; opcode handlers perform such reads. Out of scope: importing and_a into emulator/cpu/opcodes.py` and every AND opcode (lessons 117-124), plus the ORA, EOR, and BIT symbols in lessons 125-145.

Run this lesson

uv run pytest tests/chapter_01_cpu/test_116_instruction_and_a.py -v