Recursion: factorial and Fibonacci

Two subroutines that call themselves, each call keeping its own n on the stack, and the sixteen bits that put a limit on how far factorial can go.

Two subroutines that call themselves. factorial(8) comes back as 40320 in ix, and fib(10) comes back as 55 in hl, and neither of them has a loop for the repetition: the repetition is the calls.

Stack arguments and a stack frame built one frame for one call. Recursion needs nothing added to that, because call pushes at wherever sp happens to be, so every call gets its return address at a fresh place and anything the subroutine pushes is private to that call for the same reason.

You need to know: the "Stack arguments and a stack frame" Example and the "call, ret and passing values" lecture. What is new here is a subroutine calling itself, and push af as the way each call keeps its own copy of n.

The push af before each recursive call is the line that makes recursion work. n is in a, one register that every call would otherwise share, so each call puts its own copy on the stack, where the address it lands at is different for every call and no other call can reach it. The pop af after the call takes back the n that this call pushed, and the answer coming back in hl is untouched by either.

push af is also the only way to push a single byte on this machine: push and pop always move sixteen bits and always name a pair, so push a is not an instruction and the flags come along with the accumulator whether you want them or not. That is harmless here, since nothing after a pop af reads a flag, and it is what lets a single byte travel on a stack that only moves pairs.

factorial takes four bytes of stack per call, two for the return address and two for the push af, and fib takes six in the middle of its second call. The deepest point of the whole run is sp at FFD7, forty bytes below where it started, and the memory panel on FFD0 shows what is lying there afterwards.

The multiplication at the end of factorial is n additions, because the Z80 has no mulu. It is one add hl, de per unit of n, so 8! costs 2 + 3 + 4 + 5 + 6 + 7 + 8 additions on top of the calls, and the whole program is 1836 instructions. fib is the expensive half: fib(n) calls itself twice, so the number of calls roughly doubles for every 1 you add to n, for a number you could get with a loop and two registers. Recursion is written to be read, not to be quick.

Try changing ld a, 8 to ld a, 9. ix comes out at 8980, which is 35200 and simply wrong: 9! is 362880, and hl is sixteen bits, so everything above 65535 was thrown away as the additions wrapped.