014. Instruction lda
Extract the LDA instruction mechanism.
Lesson 14 of 356 · tests/chapter_01_cpu/test_014_instruction_lda.py
Files to update
emulator/cpu/instructions.py
emulator/cpu/cpu.pyLocations
instructions.lda
CPU.step, existing $A9 and $AD branchesWhy this step exists
An instruction defines the state transition after an operand is available. LDA always stores a value in A and updates Z/N, regardless of how that value was addressed.
Complete example implementation
# emulator/cpu/instructions.py
def lda(cpu, value: int) -> None:
cpu.a = value
cpu._update_zero_and_negative_flags(value)
# emulator/cpu/cpu.py
from emulator.cpu.addressing_modes import absolute, immediate
from emulator.cpu.instructions import lda
class CPU:
def step(self) -> None:
opcode = self.fetch_byte()
if opcode == 0xA9:
return lda(self, immediate(self))
if opcode == 0xAD:
return lda(self, self.bus.read(absolute(self)))
raise NotImplementedError(
f"Opcode {opcode:02X} not implemented"
)Important boundaries
- immediate returns a value, while absolute returns an address to dereference
- CPU.step selects the addressing mode
- lda changes CPU state and flags
Common misconception
lda should not fetch instruction bytes. If it did, instruction behavior would become coupled to one addressing mode.
Out of scope
- zero-page LDA
- opcode-handler functions and OPCODE_TABLE
- other load instructions
Run this lesson
uv run pytest tests/chapter_01_cpu/test_014_instruction_lda.py -v