COA Notes
Assembly language procedure calls, stack frames, calling conventions, and parameter passing.
Introduction
Functions (procedures, subroutines) are the building blocks of all software. But when you call a function in C or Java, what actually happens at the hardware level? The CPU must save its current position, pass parameters, jump to the function code, allocate space for local variables, execute, and then restore everything when returning. All of this happens through carefully choreographed register and stack manipulation. Understanding procedure calls at the assembly level is crucial for debugging, security (buffer overflow attacks exploit the stack), and writing efficient code.
The Procedure Call Mechanism
When a function calls another function, these steps occur:
Caller (the function making the call)
1. Place arguments in designated registers ($a0-$a3) or stack
2. Save any caller-saved registers it needs preserved
3. Execute JAL (Jump And Link) — saves return address in $ra, jumps to callee
Callee (the function being called)
4. Allocate stack frame (adjust $sp)
5. Save callee-saved registers and $ra (if making further calls)
6. Execute function body
7. Place return value in $v0/$v1
8. Restore saved registers
9. Deallocate stack frame
10. Execute JR $ra (Jump Register — return to caller)
The Stack Frame
Each active function has a stack frame (activation record):
Stack Frame Operations in MIPS
function:
# PROLOGUE — set up stack frame
addi $sp, $sp, -32 # Allocate 32 bytes (8 words)
sw $ra, 28($sp) # Save return address
sw $fp, 24($sp) # Save old frame pointer
sw $s0, 20($sp) # Save callee-saved register
sw $s1, 16($sp) # Save another if needed
addi $fp, $sp, 28 # Set frame pointer
# BODY — function code here
# ... use $s0, $s1 freely — they are saved
# ... local vars at 0($sp), 4($sp), etc.
# EPILOGUE — restore and return
lw $s1, 16($sp) # Restore $s1
lw $s0, 20($sp) # Restore $s0
lw $fp, 24($sp) # Restore frame pointer
lw $ra, 28($sp) # Restore return address
addi $sp, $sp, 32 # Deallocate stack frame
jr $ra # Return to callerParameter Passing
In Registers (fast, preferred)
MIPS convention: first 4 arguments in $a0-$a3, return values in $v0-$v1:
# Calling: result = add_three(10, 20, 30)
li $a0, 10 # First argument
li $a1, 20 # Second argument
li $a2, 30 # Third argument
jal add_three # Call function
move $s0, $v0 # Save return value
add_three:
add $v0, $a0, $a1 # $v0 = arg1 + arg2
add $v0, $v0, $a2 # $v0 += arg3
jr $ra # Return (result in $v0)On Stack (when registers insufficient)
For functions with more than 4 arguments:
# Calling func(a, b, c, d, e, f) — 6 arguments
li $a0, 1 # arg 1 in register
li $a1, 2 # arg 2 in register
li $a2, 3 # arg 3 in register
li $a3, 4 # arg 4 in register
addi $sp, $sp, -8 # Make room for args 5-6 on stack
li $t0, 5
sw $t0, 0($sp) # arg 5 on stack
li $t0, 6
sw $t0, 4($sp) # arg 6 on stack
jal func
addi $sp, $sp, 8 # Clean up stackRecursive Functions
Recursion requires saving state on each call because the same function uses the same registers:
# Factorial: fact(n) = n * fact(n-1), fact(0) = 1
factorial:
# Prologue
addi $sp, $sp, -8
sw $ra, 4($sp) # Must save $ra (we call ourselves!)
sw $a0, 0($sp) # Save argument n
# Base case
slti $t0, $a0, 2 # if n < 2
beq $t0, $zero, recurse
li $v0, 1 # return 1
j fact_return
recurse:
addi $a0, $a0, -1 # n-1
jal factorial # recursive call (overwrites $ra!)
# After return: $v0 = fact(n-1)
lw $a0, 0($sp) # Restore original n
mul $v0, $a0, $v0 # result = n * fact(n-1)
fact_return:
# Epilogue
lw $ra, 4($sp) # Restore return address
addi $sp, $sp, 8 # Deallocate frame
jr $ra # ReturnFor factorial(4), the stack grows 4 frames deep, each saving its own $ra and $a0.
Calling Conventions
Caller-Saved vs Callee-Saved
| Category | MIPS Registers | Rule |
|---|---|---|
| Caller-saved (temporary) | $t0-$t9, $a0-$a3, $v0-$v1 | Callee can freely overwrite; caller must save if needed |
| Callee-saved (preserved) | $s0-$s7, $sp, $fp, $ra | Callee must save before using and restore before returning |
Why the distinction? It minimizes total save/restore operations. Short leaf functions (that do not call others) need not save anything — they use $t registers and return. Only functions that call other functions need to save $ra and $s registers.
Leaf vs Non-Leaf Functions
Leaf function (calls no other functions):
leaf_add: # No stack frame needed!
add $v0, $a0, $a1 # Just compute and return
jr $ra # $ra still valid (nobody overwrote it)Non-leaf function (calls other functions):
non_leaf:
addi $sp, $sp, -4
sw $ra, 0($sp) # MUST save $ra (JAL will overwrite it)
jal some_function # This overwrites $ra
lw $ra, 0($sp) # Restore our return address
addi $sp, $sp, 4
jr $ra # Now we can return correctlyBuffer Overflow and Stack Security
Understanding the stack frame explains buffer overflow attacks:
If a program copies user input into a local buffer without bounds checking, the input can overflow into the saved return address, redirecting execution to attacker-controlled code. This is why modern systems use:
- Stack canaries: Random values between buffer and return address (detect corruption)
- ASLR: Randomize stack address (attacker cannot predict target)
- DEP/NX bit: Mark stack as non-executable (cannot run shellcode on stack)
Key Takeaways
- Procedure calls use a disciplined protocol: save state → pass arguments → jump → execute → restore → return
- The stack frame stores saved registers, return address, and local variables for each active function
- Caller-saved vs callee-saved convention minimizes unnecessary register saving
- Recursive functions require stack frames because each invocation needs its own saved state
- The return address ($ra) must be saved on the stack in any function that calls another function
- Stack-based procedure calls are the foundation of both high-level function calls and security vulnerabilities (buffer overflows)
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for Procedure Calls.
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, procedure, calls
Related Computer Organization & Architecture Topics