Addressing Modes in a CPU: Concepts and Worked Examples
In a CPU, an instruction often needs an operand (a value to use or a memory location to read/write). An addressing mode specifies how the CPU interprets the operand field in the instruction—either as an immediate value or as a way to compute an effective address (EA). This matters for both performance (how quickly operands are found) and correctness (which exact memory location is referenced).
At a high level, addressing modes fall into two categories:
- Register/immediate-like modes: the operand is in the instruction itself or in a CPU register.
- Memory-reference modes: the operand is found by computing an address using a base register, index register, displacement/offset, scaling, or indirection.
A useful mental model is:
- The instruction contains some bits naming registers and/or constants.
- The CPU applies the addressing-mode rule to determine either:
- the operand value directly, or
- the effective address, then reads/writes memory at that EA.
Key terms you’ll see repeatedly:
- effective address
- displacement/offset
- base register
- index register
- indirection
Addressing Modes (General CPU Concepts)
Common addressing modes (with what they mean)
Different CPU ISAs describe addressing modes slightly differently, but the underlying patterns are consistent.
-
Immediate addressing
- The operand value is embedded in the instruction itself.
- Example idea:
ADD R1, #5means “add 5 to R1”.
-
Register addressing
- The operand is in a named register.
- Example idea:
ADD R1, R2.
-
Direct (absolute) memory addressing
- The instruction contains (or refers to) a full memory address constant.
- Example idea:
LOAD R1, [0x1000].
-
Register indirect
- A register contains the memory address (a pointer).
- Example idea:
LOAD R1, [R3]whereR3points to the memory location.
-
Base + displacement (base-relative)
- Effective address is formed as
EA = Base + displacement. - Example idea:
LOAD R1, [Rbp + 8].
- Effective address is formed as
-
Index (indexed) addressing
- Effective address includes an index register (often with a scale).
- Example idea:
LOAD R1, [Rbase + Rindex]orEA = base + index*scale.
-
Base + index + displacement
- Common in array access and data structures.
- Often:
EA = base + index*scale + displacement.
-
Scaled indexed addressing
- A scale factor accounts for element size (e.g., 4 bytes for 32-bit ints).
- Example idea:
EA = base + index*4.
Note: Exact syntax differs by ISA (e.g., x86 uses “effective address” with forms like base+index*scale+disp; ARM uses variants for load/store and register+offset forms). The conceptual structures above still apply.
Pro Tip: Translate every memory operand into an EA formula
When you see LOAD/STORE with brackets like [ ... ], write an explicit expression (e.g., ). This makes it immediately clear which memory location is accessed.
Worked example: computing an operand address with multiple addressing modes
- 1Step 1
Assume: , , and memory is byte-addressed. Suppose (so the word at/starting near address 1012 has value 42 for this example).
- 2Step 2
If the instruction is
ADD R1, #5, then the operand value is directly—no EA computation. - 3Step 3
If the instruction is
ADD R1, R2and , then the operand value is (again, no EA). - 4Step 4
For
LOAD R1, [Rptr]with , compute , then read . - 5Step 5
For
LOAD R1, [Rbase + 12]: compute , then read . - 6Step 6
For an array of 4-byte ints,
LOAD R1, [Rbase + Ridx*4]: compute , then read . - 7Step 7
For
LOAD R1, [Rbase + Ridx*4 + 8]: compute . The operand is at .
Visual comparison of the EA rules
The table below focuses on how the effective address is computed (or whether an EA is needed at all).
| Addressing mode | Example operand syntax (conceptual) | Effective address rule |
|---|---|---|
| Immediate | #const | No ; operand value is |
| Register | Rk | No ; operand value is |
| Direct/absolute memory | [addr] | |
| Register indirect | [Rptr] | |
| Base + displacement | [Rbase + disp] | |
| Indexed (base + index) | [Rbase + Ridx] | |
| Scaled indexed | [Rbase + Ridx*scale] | |
| Base + index + displacement | [Rbase + Ridx*scale + disp] |
Relative conceptual complexity of finding the operand
A qualitative view: fewer computations for immediate/register; more arithmetic for base+index+disp forms.
Common pitfalls when reasoning about addressing modes
Worked “one loop” example: array element access via different modes
Consider accessing A[i] where A is an array of 4-byte integers.
Assume:
- holds the base address of
A - holds the integer index
- Each element is 4 bytes
Then the memory read uses:
- Scaled indexed addressing:
So a conceptual LOAD Rval, [Rbase + R_i*4] reads , i.e., the value at A[i].
In contrast:
- Immediate addressing would not make sense for array indexing because varies per iteration, and immediate addressing fixes the operand value at assembly time.
- Register indirect could be used if you first compute a pointer to
A[i](e.g., compute somewhere, thenLOAD Rval, [Rptr]).
This is why modern compilers and ISAs emphasize addressing-mode arithmetic: it reduces extra instructions by folding address calculation into the load/store itself.
Addressing Modes Quick Check
Knowledge Check
In base+displacement addressing, the effective address is best modeled as: