COA Notes
Implementing loop constructs in assembly language: for, while, do-while, and nested loops.
Introduction
Loops are the workhorses of programming — they repeat operations thousands or millions of times. In high-level languages, you write for or while and the compiler handles the details. In assembly, YOU handle the details: initializing a counter, comparing it each iteration, branching back or forward, and managing the loop body. Understanding how loops work at the assembly level explains why some code runs fast and other code is slow — it all comes down to how many instructions execute per iteration and how branches interact with the pipeline.
Loop Anatomy in Assembly
Every loop in assembly has four components:
| 1. INITIALIZATION | Set up counter/pointer before the loop |
| 2. BODY | The actual work of each iteration |
| 3. UPDATE | Modify counter/pointer for next iteration |
| 4. CONDITION + BRANCH | Test if loop should continue, branch back or exit |
For Loop
High-level: for (int i = 0; i < 10; i++) { sum += i; }
Execution trace:
Total instructions per iteration: 4 (bge, add, addi, j) → very tight loop.
While Loop
High-level: while (n > 1) { if (n%2==0) n=n/2; else n=3*n+1; count++; }
(Collatz conjecture)
Architecture insight: The srl (shift right logical) for division by 2 is ONE cycle. An actual div instruction would take 30+ cycles!
Do-While Loop
High-level: do { read input; } while (input != 0);
li $t1, 0 # sum = 0
do_while:
# BODY executes at least once
li $v0, 5 # Read integer
syscall
move $t0, $v0 # input in $t0
add $t1, $t1, $t0 # sum += input
bnez $t0, do_while # CONDITION: repeat if input != 0
# When we get here, user entered 0
move $a0, $t1
li $v0, 1
syscall # Print sumThe key difference: condition is checked at the END, so the body always executes at least once.
Nested Loops
Multiplication table (5×5):
Loop Optimization Techniques
1. Loop Unrolling
Process multiple elements per iteration to reduce branch overhead:
# Original: 1 element per iteration (4 instructions overhead per element)
loop:
lw $t0, 0($t1)
add $t2, $t2, $t0
addi $t1, $t1, 4
addi $t3, $t3, -1
bnez $t3, loop
# Unrolled: 4 elements per iteration (4 instructions overhead per 4 elements)
loop_unrolled:
lw $t0, 0($t1)
lw $t4, 4($t1)
lw $t5, 8($t1)
lw $t6, 12($t1)
add $t2, $t2, $t0
add $t2, $t2, $t4
add $t2, $t2, $t5
add $t2, $t2, $t6
addi $t1, $t1, 16
addi $t3, $t3, -4
bnez $t3, loop_unrolledBenefit: Branch overhead reduced from 25% to 7% of instructions.
2. Strength Reduction
Replace expensive operations with cheaper equivalents:
# Expensive: multiply in each iteration
mul $t0, $t1, $t2 # Array offset = i × element_size (3-5 cycles)
# Cheap: incremental addition
addi $t0, $t0, 4 # Just add element_size each time (1 cycle)3. Loop Invariant Code Motion
Move calculations that do not change inside the loop to outside:
# Bad: recalculates array base every iteration
loop:
la $t0, array # REDUNDANT — same every iteration
add $t0, $t0, $t1
lw $t2, 0($t0)
...
# Good: calculate once before loop
la $t0, array # Only once!
loop:
add $t3, $t0, $t1
lw $t2, 0($t3)
...Performance Analysis
A loop with N iterations and B instructions per body:
This is why loop unrolling helps — it amortizes the 3-instruction overhead over more useful work.
Why Loops Matter for Architecture
- Branch prediction: Loop back-branches are highly predictable (taken N-1 times, not-taken once). Predict-taken works well.
- Cache behavior: Loops re-execute the same instructions — excellent temporal locality in I-cache.
- Pipeline utilization: The backward branch at loop end is predicted correctly ~99% of the time in a counted loop.
- Data prefetching: Sequential array access in loops has perfect spatial locality — hardware prefetchers love this pattern.
Key Takeaways
- Every loop needs initialization, body, update, and conditional branch — the branch makes it a loop
- For loops check the condition at the top (may execute zero times); do-while checks at bottom (always executes once)
- Nested loops require resetting the inner counter on each outer iteration
- Loop overhead (compare + branch + update) can be 25-50% of total instructions — unrolling reduces this
- Loops are where programs spend most of their time — optimizing loop bodies has the highest performance impact
- From the CPU perspective, a loop is just a backward branch that is almost always taken — branch predictors handle this efficiently
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for Loops in Assembly.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this Computer Organization & Architecture topic.
Search Terms
computer-organization, computer organization & architecture, computer, organization, assembly, language, loops, loops in assembly
Related Computer Organization & Architecture Topics