013. Addressing modes inmediate absolute

Extract immediate and absolute addressing modes.

Lesson 13 of 356 · tests/chapter_01_cpu/test_013_addressing_modes_inmediate_absolute.py

Files to update

emulator/cpu/addressing_modes.py
emulator/cpu/cpu.py

Locations

addressing_modes.immediate
addressing_modes.absolute
CPU.step, existing $A9 and $AD branches

Why this step exists

Addressing modes determine where an instruction gets its operand. Separating that mechanism keeps CPU.step focused on opcode selection while preserving the behavior already established for immediate and absolute LDA.

Complete example implementation

# emulator/cpu/addressing_modes.py
def immediate(cpu) -> int:
    return cpu.fetch_byte()


def absolute(cpu) -> int:
    return cpu.fetch_word()


# emulator/cpu/cpu.py
from emulator.cpu.addressing_modes import absolute, immediate


class CPU:
    def step(self) -> None:
        opcode = self.fetch_byte()

        if opcode == 0xA9:
            self.a = immediate(self)
        elif opcode == 0xAD:
            address = absolute(self)
            self.a = self.bus.read(address)
        else:
            raise NotImplementedError(
                f"Opcode {opcode:02X} not implemented"
            )

        self._update_zero_and_negative_flags(self.a)

Important distinction

immediate(cpu) returns a value. absolute(cpu) returns an address that the opcode path must dereference through the bus.

Common misconception

Do not make every addressing mode return a loaded value. Store instructions will also need addresses, so address-producing modes should remain independent of LDA.

Out of scope

  • instructions.lda, introduced in Test 014
  • zero-page and indexed addressing
  • an opcode table

Run this lesson

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