Pointers and Index Registers
So far, we've used direct addressing: LDA 50 always reads from address 50. But what if you need to process an array of 100 numbers? Writing 100 different LDA instructions — one for each address — is absurd. You need a way to say "read from whatever address this register points to."
This is indirect addressing. Instead of the instruction containing the address, it contains a register number, and that register contains the address. LDA (X) means "load the accumulator from the address stored in register X." To walk through an array, you just increment X and run the same instruction in a loop.
An index register takes this further. It works like a pointer but adds an offset from the instruction itself: LDA 100, X means "load from address (100 + X)." If X is 0, you read address 100. If X is 5, you read 105. The base address (100) is hardcoded in the program; the index (X) varies at runtime.
Practical example. You're writing a program that initializes 256 bytes of RAM to zero. With direct addressing, you'd need 256 separate STA instructions — a nightmare. With an index register: set X to 0, then loop 256 times: STA 0,X (store zero at address X); increment X; if X < 256, jump back. Four instructions do the work of 256. This is the power of pointers.