Exercises — Memory addressing modes — immediate, register, direct, indirect, indexed
Throughout, we reuse one memory snapshot (the "world" for these problems):

Level 1 — Recognition
L1-1
State the addressing mode named by each instruction, and the number of operand memory accesses it needs.
- (a)
MOV R1, #100 - (b)
LOAD R1, [100] - (c)
LOAD R1, [[100]] - (d)
ADD R1, R2 - (e)
LOAD R1, [100 + R2]
Recall Solution L1-1
(a) Immediate — the number 100 is the data, sitting in the instruction word. 0 accesses.
(b) Direct — [100] is a literal address. EA , operand . 1 access.
(c) Indirect — double brackets mean "the address of the address". EA , operand . 2 accesses.
(d) Register — both operands live in CPU registers. 0 memory accesses.
(e) Indexed — base 100 plus index register R2. EA , operand . 1 access.
Memory-access digits, in mode order (Imm, Reg, Direct, Indirect, Indexed) .
L1-2
Which single mode requires two memory reads to fetch its operand, and why exactly two?
Recall Solution L1-2
Indirect. Read #1 fetches the pointer (this is the EA). Read #2 fetches the operand . Every $M[\cdot]$ in the EA recipe costs one read; indirect's recipe is , which contains one $M[\cdot]$, so 1 (resolve) + 1 (final fetch) .
Level 2 — Application
L2-1
Using the shared state, compute the operand value loaded into R1 for each:
- (a)
MOV R1, #100 - (b)
LOAD R1, [100] - (c)
LOAD R1, [[100]] - (d)
LOAD R1, [100 + R2]
Recall Solution L2-1
(a) Immediate: operand . . (b) Direct: EA , operand . . (c) Indirect: EA , operand . . (d) Indexed: EA , operand . .
L2-2
R3=104. Evaluate LOAD R1, [[R3 - 4]] — a register-indirect with an offset inside the brackets. Assume [X] means read .
Recall Solution L2-2
Innermost first: . First read: → this is the EA. Second read (outer bracket): . . Two memory accesses (double brackets).
L2-3
An array of 4-byte integers is based at address . Register R2 holds a byte offset. What value of R2 selects element index 1 (the second element), and what operand does LOAD R1, [100 + R2] fetch then?
Recall Solution L2-3
Element index lives at byte offset . For , elemSize : offset , so R2 = 4.
EA , operand . .
This is exactly why indexed mode walks arrays: bump R2 by 4 each loop, reuse the same instruction.
Level 3 — Analysis
L3-1
Two instructions land at the same operand but by different routes. Given the shared state, show that
LOAD R1, [[300]] and LOAD R1, [100] both put 200 into R1. Then state which is faster and by how many memory accesses.
Recall Solution L3-1
Indirect route [[300]]: read (EA), then read . . 2 accesses.
Direct route [100]: EA , read . . 1 access.
Same result 200; direct is faster by 1 memory access. The indirect version paid an extra read to chase the pointer stored at 300.
L3-2
You see LOAD R1, [100 + R2] with R2=104. A classmate claims "this is indirect, because points somewhere." Refute this precisely, then give the operand.
Recall Solution L3-2
It is indexed, not indirect. The distinction: indexed performs an addition with no extra memory read; indirect performs an extra memory read . Here EA (pure arithmetic, no dereference of 's "target"). Operand . . 1 memory access — proving it is not indirect (which would be 2).
L3-3
For each mode, if the instruction lives at a fixed spot but you want it to touch a different memory cell on the next run without rewriting the instruction bits, which modes can do it and how?
Recall Solution L3-3
- Immediate: ❌ operand is baked into the bits — fixed forever.
- Register: operand target is a fixed register number, but its contents can change → the value differs, though not the memory cell (no memory involved).
- Direct: ❌ address
Ais literal in the bits — same cell every time. - Indirect: ✅ change the contents of (the pointer) and the same instruction reaches a new target.
- Indexed: ✅ change the index register ; EA moves without touching the bits. Conclusion: runtime retargeting needs a changeable piece (register or a memory pointer) — indexed and indirect. This is why loops and pointers use them.
Level 4 — Synthesis
L4-1
Write a 3-instruction loop body (pseudocode) that sums a 4-byte-integer array based at A=100 using indexed mode, and explain why immediate/direct modes cannot express this loop compactly.
Recall Solution L4-1
LOAD R1, [100 + R2] ; fetch current element (indexed)
ADD Racc, R1 ; accumulate (register mode)
ADD R2, #4 ; advance byte offset by one 4-byte element (immediate)
(plus a branch to repeat until R2 reaches the array's byte-length).
Why not immediate/direct? Immediate bakes a constant in the bits — it cannot name a moving cell. Direct bakes a fixed address — you'd need a separate LOAD for every element ([100], [104], [108], …), i.e. unrolled code proportional to array size. Indexed reuses one instruction while the index register moves the EA. Note all three modes appear: indexed (fetch), register (accumulate), immediate (the stride #4).
L4-2
A linked-list node stores {value at offset 0, next-pointer at offset 4}. The head node is at address 300. Given M[300]=100, M[304]=200, M[100]=200, M[200]=350, M[104]=42, write the accesses to (a) read the head node's value, and (b) advance to the next node's address. Which mode(s) does each use?
Recall Solution L4-2
(a) head value = field at offset 0 of node@300 → M[300]. If we LOAD R1, [300] that's direct, giving . So head value . 1 access.
(b) next pointer = field at offset 4 of node@300 → LOAD R1, [300 + 4] (indexed, offset 4) reads . So the next node's address is 200. 1 access.
To then read the next node's value: LOAD R1, [[300 + 4]] — indexed-then-indirect: read (the pointer), then . 2 accesses, value . This is the classic "follow the chain" pattern: indexed picks the pointer field, indirect follows it.
Level 5 — Mastery
L5-1
Design task. Your ISA has a 16-bit instruction: 4-bit opcode, 2-bit mode field, and a 10-bit operand field. (i) How many distinct addressing modes can the 2-bit field encode? (ii) In direct mode, what is the largest byte address the 10-bit field can name? (iii) Argue why indexed mode lets this small machine still reach far beyond that limit.
Recall Solution L5-1
(i) 2 bits encode modes. (ii) 10 bits name distinct addresses, i.e. addresses through . Largest direct address . (iii) In indexed mode EA . The base (10 bits) is small, but the index register is full machine-width (say 16+ bits). Since the register supplies most of the address at runtime, EA can far exceed 1023 — the register carries the high bits the instruction word cannot. This is exactly how small instruction words still address large memories: put the big number in a register, not the instruction.
L5-2
Cost analysis. A program does operand fetches. 40% are indirect, 35% are indexed, 25% are direct. If one memory access costs 5 ns and an ALU addition (for indexed) costs 1 ns, compute total operand-access time. (Register/immediate parts excluded.)
Recall Solution L5-2
Counts: indirect , indexed , direct .
- Indirect: 2 accesses each → ns.
- Indexed: 1 access + 1 addition each → ns.
- Direct: 1 access each → ns. Total ns. Notice indirect, though only 40% of fetches, dominates the cost (4000 of 7350 ns) — because of its 2-access penalty. This is the quantitative reason pointer-heavy code is slow (see Memory Hierarchy and Access Latency).
Recall One-line recap of the whole ladder
Recognise the mode (L1) → compute its operand from state (L2) → separate value from cost/flexibility (L3) → build loops & pointer-chases from modes (L4) → reason about encoding limits & timing (L5). The invariant behind all of it: EA is a recipe; each $M[\cdot]$ in that recipe is a real memory read.
Related: Instruction Encoding & Opcodes · Registers and the Register File · Pointers in C · Arrays and Stride · CPU Datapath and Control Unit.