Sikau

Assembly language · Day 6 · about 40 min

The stack and recursion

Stack frames, why recursion needs them, and Fibonacci in assembly.

Every call gets its own frame

A recursive function calls itself — so each call needs its *own* saved ra and its own copy of n. That's exactly what the stack gives you: every call pushes a stack frame and pops it on return. It's the same stack that overflows when JavaScript recursion goes too deep.

# fib(a0 = n) -> a0 = fib(n), with fib(0) = 0 and fib(1) = 1
fib:
  li   t0, 2
  blt  a0, t0, base    # n < 2: the answer is n itself
  addi sp, sp, -12
  sw   ra, 8(sp)
  sw   s0, 4(sp)
  sw   s1, 0(sp)
  mv   s0, a0
  addi a0, s0, -1
  call fib             # fib(n - 1)
  mv   s1, a0
  addi a0, s0, -2
  call fib             # fib(n - 2)
  add  a0, a0, s1
  lw   s1, 0(sp)
  lw   s0, 4(sp)
  lw   ra, 8(sp)
  addi sp, sp, 12
base:
  ret

What goes in fib's frame

Each fib call needs three things after its first recursive call returns: its own return address, its own n (to compute n − 2), and the result of fib(n − 1) while it computes fib(n − 2). That's three words, 12 bytes. Every active call has its own 12-byte frame, so nothing one call saves is overwritten by another.

fib:
  li   t0, 2
  blt  a0, t0, base
  addi sp, sp, -12
  sw   ra, 8(sp)
  sw   s0, 4(sp)
  sw   s1, 0(sp)
  mv   s0, a0          # n
  addi a0, s0, -1
  call fib             # fib(n - 1)
  mv   s1, a0
  addi a0, s0, -2
  call fib             # fib(n - 2)
  add  a0, a0, s1
  lw   s1, 0(sp)
  lw   s0, 4(sp)
  lw   ra, 8(sp)
  addi sp, sp, 12
base:
  ret

The rest of this lesson

  • Depth and costexplain
  • A function's frameorder
  • How deep?predict
  • Frame contentsmatch
  • Recursive Fibonacciwrite code
  • Badge quizquiz
  • What you learnedrecap

Continue this lesson free — run real code in your browser

Continue with Google

See all 12 lessons of Assembly language