LD I, addr — Setting the Index Register

Every time the CPU needs to read from or write to memory — drawing a sprite, loading a font, storing register values — it has to know where to look. That is what the index register I is for. And ANNN is the instruction that points it there.

Encoding

ANNN
│└──┘
│  └─ NNN: 12-bit address
└──── opcode category A

Example: 0xA300 sets I to address 0x300.

Decode and execute

#![allow(unused)]
fn main() {
0xA => {
    let nnn = opcode & 0x0FFF;
    self.i = nnn;
}
}

Structurally identical to JP (1NNN) — extract the lower 12 bits and assign them. The only difference is the destination register: pc for JP, I here.

I as a prerequisite

Think of LD I as setup. It rarely does anything visible on its own. Its purpose is to prepare the ground for whatever comes next:

  • Before drawing a sprite, I must point at the sprite bytes in memory.
  • Before drawing a digit, FX29 uses I to point at the font sprite for that digit.
  • Before storing registers to memory with FX55, I must point at the destination.
  • Before reading registers back with FX65, I must point at the source.

In almost every non-trivial sequence of CHIP-8 instructions, a LD I — or an opcode that sets I like FX29 — appears just before the operation that needs it. It is the pointer setup step.

Test

#![allow(unused)]
fn main() {
#[test]
fn test_ld_i_addr() {
    let mut cpu = Cpu::new();
    // 0xA300 = LD I, 0x300
    cpu.memory.load_rom(&[0xA3, 0x00]);
    cpu.step();
    assert_eq!(cpu.i, 0x300);
}
}

In the test program

The test program in main.rs draws the 16 hex digit sprites across the screen. Each iteration uses FX29 rather than ANNN directly — but FX29 is really just a specialized form of LD I that calculates the font address for you:

0xF0, 0x29,  // LD F, V0  — I = address of font sprite for digit in V0
0xD1, 0x25,  // DRW V1, V2, 5 — draw from I at position (V1, V2)

FX29 sets I, then DRW reads from I. The pattern is always the same: point first, then act.


Rust concepts used here: The 0x0FFF mask follows the same bitwise pattern established in The First Opcode: JP. The role of I in the CPU is introduced in Registers and the CPU. See DRW — Drawing Sprites for the most common use of I, and Font Sprites for how FX29 works.