;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; This is essentially the book's recursive-factorial. The ;; main difference is in the comments, which I pared down, ;; and which I altered to talk about "caller/callee". ;; Otherwise, I permuted two instructions in order to clarify ;; the caller/callee. allocate-registers n, continuation, val allocate-registers factorial, base-case allocate-registers sp allocate-registers one li one, 1 li factorial, factorial-label li base-case, base-case-label li sp, 0 read n li continuation, after-top-level factorial-label: ;; computes the factorial of n into val and jumps to continuation; ;; doesn't touch the first sp locations of memory and restores ;; sp back to its entry value when continuation is jumped to; jeqz n, base-case ;; save n and continuation onto stack so callee can do its thing st n, sp add sp, sp, one st continuation, sp add sp, sp, one ;; Record that we need to do after-recursive-invocation cleanup ;; after callee has completed li continuation, after-recursive-invocation ;; Now we can set up for (n-1)! (callee) sub n, n, one j factorial after-recursive-invocation: ;; We have computed current n! into val, for a recursive call, ;; so we need to finish things up for the caller ;; First restore n and continuation to caller state sub sp, sp, one ld continuation, sp sub sp, sp, one ld n, sp ;; having retrieved n and continuation and set sp back to the way it ;; was on entry (since it went up by two and back down by two) ;; we are ready to compute n! as (n-1)! * n, i.e. val * n, ;; putting the result into val, and jump to the continuation mul val, val, n j continuation base-case-label: ;; this is the n = 0 case, which is trivial li val, 1 j continuation after-top-level: ;; when the top level factorial has put n! in val, it jumps here write val ; to display that result halt ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Here is a slim program that computes fibonacci, ;; allocate-registers n, result, temp, comparison allocate-registers sp, continuation allocate-registers zero, one allocate-registers fibonacci, fibonacci-base li zero, 0 li one, 1 li sp, 0 li fibonacci, fibonacci-label li fibonacci-base, fibonacci-base-label read n li continuation, end-label fibonacci-label: ;; Computes fib(n) into result and jumps to the address in continuation. ;; The registers temp is used to store the intermediate computation. ;; The registers n, temp, and continuation are saved and restored to ;; their original values using stack discipline. sgt comparison, n, one jeqz comparison, fibonacci-base st n, sp ; push n, temp, and continuation add sp, sp, one st temp, sp add sp, sp, one st continuation, sp add sp, sp, one li continuation, after-first-invocation-label sub n, n, one j fibonacci after-first-invocation-label: add temp, result, zero ; store fib(n-1) in temp sub n, n, one li continuation, after-second-invocation-label j fibonacci after-second-invocation-label: add result, temp, result ; fib(n-1) + fib(n-2) into result sub, sp, sp, one ; pop continuation, temp, and n ld continuation, sp sub sp, sp, one ld temp, sp sub sp, sp, one ld n, sp j continuation fibonacci-base-label: add result, n, zero ; if n=0 or 1, fib(n) = n j continuation end-label: write result halt ; Following are instruction counts for various input (n) values: ; ; ; n # instructions ; ; 1 13 ; 2 40 ; 3 67 ; 4 121 ; 5 202 ; 6 337 ; 7 553 ; 8 904 ; 9 1471 ; 10 2389