Carlos R. answered 08/22/26
Ivy League CS Graduate with 45+ Years of Programming Experience
When you’re first learning assembly, direct addressing feels almost too simple. The instruction has the memory address sitting right there in its bits. The CPU treats that number as the effective address, goes straight to that location, and pulls the operand. One memory access and you’re done. Fast, no extra calculation, nothing to go wrong.
Then the limitations show up. Instruction formats are cramped; a lot of machines only leave you 8 or 12 bits for an address field, so direct mode can only see a small corner of memory. And if the data ever needs to move, or you’re working with a table whose size isn’t known until the program is running, you’re stuck. Changing the address means rewriting the instruction itself.
Indirect addressing is the extra hop that people invented to get around that. The number in the instruction isn’t the data’s address — it’s the address of a pointer. The processor has to fetch that pointer first (from memory or a register), then use *that* as the real address and make a second trip for the actual operand. Two references instead of one, so it’s slower. You feel it in a tight loop.
The reason everyone puts up with the extra cycle is what you get in return. That pointer can be a full word or a full register, so suddenly you can reach the entire address space instead of being limited by the instruction encoding. Even better, you can change the pointer while the program runs. Increment it to walk an array, swap it to chase a linked list, pass it as an argument. Direct addressing can’t do any of that without self-modifying code.
That’s the actual tradeoff. Direct is quicker and simpler when the location is known and never changes. Indirect costs you a memory cycle but gives you range and the ability to treat addresses as data you can manipulate. Pretty much everything interesting in software ended up depending on the second one.