sicp.io
5.5.5 · An example of compiled code

Recursive compiled code makes every call and return transfer explicit.

Inspect and execute a factorial controller with one entry label, one base-case label, saved continuations, and an indirect return through continue.

Guiding question

What machine state replaces the implicit call stack of a recursive source procedure?

  • Read the full assembled instruction list for one recursive procedure
  • Identify entry, after-call, base-case, and done labels
  • Save the caller continuation and live argument before a recursive call
  • Restore state before multiplying the returned value
  • Return indirectly through the continue register
  • Measure entries, instructions, maximum stack depth, and final stack balance

The compiled listing begins at factorial-entry. Every non-base call saves continue and n, decrements n, installs after-factorial as the new return address, and jumps back to the same entry. The base case places 1 in val and returns through continue. after-factorial restores the caller state, multiplies n by the returned val, and returns again.

The instrumented run starts with n = 5 and continue pointing to done. Six entries are observed, including n = 0. Five suspended calls each hold two stack values, so maximum stack depth is 10. All ten values are restored before halt. The 66 fetched instructions and exact controller listing measure this finite compiled procedure.

SICP code6,732 of 1,048,576 UTF-8 bytes
Examples
Result
Output
Value
Diagnostic
Execution trace0 / 0 events
    Programs run in the browser with their result and execution trace.
    Expected result

    The listing returns (((factorial-entry . 0) (after-factorial . 8) (base-case . 12) (done . 14)) 15 (perform test branch save save assign assign goto restore restore assign goto assign goto halt)). The run returns (15 complete 120 66 10 #t (5 4 3 2 1 0)).

    Trace focus

    Follow continue changing from done to after-factorial before each recursive jump. At the base case, trace five indirect returns through the same after-call code. Match each pair of save instructions with the later restores and verify that stack depth returns from 10 to 0 before the final goto reaches done.

    Try it yourself

    Change the program and compare the result.

    Translate a recursive Fibonacci or exponentiation procedure into the same explicit listing. State which registers remain live across each recursive call and predict the maximum stack depth for one representative input.

    Show hint

    Save exactly the continuation and values needed after the recursive result returns. A procedure with two recursive calls must also preserve the first returned value while computing the second.

    Complete this lesson

    0 of 23 lessons complete in this chapter0%