Call Stacks

All our previous work has been assuming FORTRAN-style calling conventions. In this, all procedure-local variables are actually secretly globals. This means that a function that calls itself will end up stomping on its previous values, and everything will be hideously scrambled. Various workarounds for this are covered in the Chapter called Structured Programming. Here, we solve the problem fully.

Recursion

A procedure in C or other similar languages declares a chunk of storage that's unique to that invocation. This chunk is just large enough to hold the return address and all the local variables, and is called the stack frame. Stack frames are arranged on a call stack; when a function is called, the stack grows with the new frame, and when that function returns, its frame is destroyed. Once the main function returns, the stack is empty.

Most modern architectures are designed to let you implement variable access like this directly, without touching the registers at all. The x86 architecture even dedicates a register to function explicitly as the stack pointer, and then one could read, say, the fifth 16-bit variable into the register AX with the command MOV AX, [SP+10].

As we saw in the Chapter called Pointers and Indirection, the 6502 isn't nearly as convenient. We'd need to keep the stack pointer somewhere on the zero page, then load the Y register with 10, then load the accumulator with an indexed-indirect call. This is verbose, keeps trashing our registers, and it's very, very slow.

So, in the spirit of programmers everywhere, we'll cheat.