Advanced
Recursion
Implementing recursive functions in LC-3 assembly.
Recursion in Assembly
Recursion works in assembly just like in high-level languages — a function calls itself with a smaller problem. The stack is essential because each call needs its own copies of local variables and the return address.
Factorial Example
Let's implement factorial(n):
The key insight: before the recursive call, we must save n and R7 on the stack.
.ORIG x3000
LD R6, STACK ; Initialize stack
AND R0, R0, #0
ADD R0, R0, #5 ; Compute 5!
JSR FACTORIAL ; R0 = factorial(5) = 120
HALT
;-----------------------------------
; FACTORIAL: R0 = factorial(R0)
; Input: R0 = n
; Output: R0 = n!
;-----------------------------------
FACTORIAL
ADD R6, R6, #-1
STR R7, R6, #0 ; Save return address
ADD R6, R6, #-1
STR R1, R6, #0 ; Save R1
ADD R1, R0, #0 ; R1 = n (save it)
ADD R0, R0, #-1 ; n - 1
BRp RECURSE ; if n-1 > 0, recurse
; Base case: return 1
AND R0, R0, #0
ADD R0, R0, #1
BR FACT_DONE
RECURSE
; R0 already = n-1
JSR FACTORIAL ; R0 = factorial(n-1)
; Now multiply: R0 = R1 * R0 (n * factorial(n-1))
; Simple multiply using a loop
ADD R2, R0, #0 ; R2 = factorial(n-1)
AND R0, R0, #0 ; R0 = 0 (accumulator)
ADD R1, R1, #0 ; Check R1
FMUL_LOOP
ADD R1, R1, #0
BRz FACT_DONE
ADD R0, R0, R2
ADD R1, R1, #-1
BR FMUL_LOOP
FACT_DONE
LDR R1, R6, #0 ; Restore R1
ADD R6, R6, #1
LDR R7, R6, #0 ; Restore return address
ADD R6, R6, #1
RET
STACK .FILL xFE00
.ENDEach recursive call pushes data onto the stack, and each return pops it off. For factorial(5), the stack grows 5 levels deep before unwinding.
Quiz
In a recursive subroutine, what MUST be saved on the stack before making the recursive call?