Back on lesson 7 you taught the CPU LD B, n - load an immediate into B. Real programs seed constants into every register, so today you generalize that to the whole LD r, n family by decoding which register the opcode names. It is the single biggest gap between your core and a ROM that actually boots.
Generalize LD r, n to every register by decoding the register field from the opcode.
Lesson 7 taught a single immediate load, LD B, n. But a boot sequence sets up the
stack pointer, the LCD control byte, palettes, and scroll positions - it loads
constants into every register, not just B. Hard-coding one opcode per
register would be eight near-identical cases.
Instead, notice the pattern: the eight LD r, n opcodes are 0x06, 0x0E,
0x16 … 0x3E, stepping by 8 because the destination register lives in bits
3–5 of the opcode byte. Decode that field once - ideally into a small
setReg(index, value) helper - and you have all eight at a stroke. That same
register-index trick powers the INC r and arithmetic families you generalize
next.
// The target register is encoded in bits 3-5 of the opcode:// LD B,n = 0x06, C,n = 0x0E, D,n = 0x16 ... A,n = 0x3E (stepping by 8)// Decode that 3-bit index, fetch the immediate, and store it into the named// register. Index 6 is (HL) - a write to memory at HL. A small// setReg(index, value) helper keeps this and the register families to come tidy.
The LD r, n block - one immediate-load opcode per register, the register in bits 3-5.