011. Lda 绝对寻址

添加绝对寻址的 LDA($AD)。

11 / 356 · tests/chapter_01_cpu/test_011_LDA_absolute.py

要更新的文件

emulator/cpu/cpu.py

位置

CPU.step, new $AD branch

为什么需要这一步

立即寻址的 LDA 直接加载其操作数。绝对寻址的 LDA 则消耗一个两字节的小端序地址,读取存储在该地址处的值,并应用与测试 010 中所学相同的零标志位与负标志位行为。

完整示例实现

ZERO_FLAG = 1 << 1
NEGATIVE_FLAG = 1 << 7


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

        if opcode == 0xA9:
            self.a = self.fetch_byte()
            if self.a == 0:
                self.p |= ZERO_FLAG
            else:
                self.p &= ~ZERO_FLAG

            if self.a & NEGATIVE_FLAG:
                self.p |= NEGATIVE_FLAG
            else:
                self.p &= ~NEGATIVE_FLAG
            return

        if opcode == 0xAD:
            address = self.fetch_word()
            self.a = self.bus.read(address)

            # In this step, flag behavior is intentionally
            # duplicated before Test 012 extracts the common helper.
            if self.a == 0:
                self.p |= ZERO_FLAG
            else:
                self.p &= ~ZERO_FLAG

            if self.a & NEGATIVE_FLAG:
                self.p |= NEGATIVE_FLAG
            else:
                self.p &= ~NEGATIVE_FLAG
            return

        raise NotImplementedError(
            f"Opcode {opcode:02X} not implemented"
        )

重要不变量

  • $AD 消耗三个指令字节:操作码、低位地址、高位地址
  • 总线读取使用组装完成的 16 位地址
  • Z/N 的置位与清零在连续指令之间都能正常工作

常见误解

字节 34 12 并不是加载到 A 中的值 $1234。它们组成的是地址 $1234;LDA 随后加载存储在该地址处的字节。

范围之外

  • 将共享的标志位逻辑提取到辅助函数中
  • 提取寻址函数与指令函数
  • 其他 LDA 寻址模式

运行本课

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