This causes some variables organization problems that we must deal with to make recursion work:
Parameter and local variables are created each time we invocate a function, why didn't we encounter this problem in non-recursive function invocations ?
Answer:
+---------------------+ <------------ Stack pointer | | | 0 or more | | local variables | | | +---------------------+ <------------ Frame Pointer | Saved Frame Pointer | +---------------------+ | Return Address | +---------------------+ | | | 0 or more | | parameter variables | | | | | +---------------------+
(The currently running one is the last one that was called, all other copies are suspected, waiting for some other function to return)
The called function becomes the currently running function
+----------------------+ <------ Stack pointer (top of system stack) | xxxxxx | +----------------------+ | yyyyyy | +----------------------+ | zzzzzz | +----------------------+ | ...... |The values xxxxxx, yyyyyy, zzzzzz are the 3 most recent values that were pushed on the system stack...
+----------------------+ <------ Stack pointer (top of system stack) | 0 or more | | parameter variables | | | +----------------------+ | xxxxxx | +----------------------+ | yyyyyy | +----------------------+ | zzzzzz | +----------------------+ | ...... |Notice that the stack pointer has moved and some memory reservation is made.
Since it is the caller function that passes the paramters to the callee, it is therefore the caller function that will create the parameter variables on the system stack.
+----------------------+ <------ Stack pointer (top of system stack) | Return Address | +----------------------+ | 0 or more | | parameter variables | | | +----------------------+ | xxxxxx | +----------------------+ | yyyyyy | +----------------------+ | zzzzzz | +----------------------+ | ...... |So the return address is also created by the caller function.
Notice again that the stack pointer has moved further, protecting the return address.
(How do we know this ? Well, the caller function just executed the bsr instruction and this instruction make the computer execute the first instruction that pertains to the called function.)
Notice that the stack frame is not yet complete
The called function must finish building the stack frame before it can start executing the instructions of the function itself !
So there is always a fragment of code (instructions) at the start of a recursive function that is used to complete the stack frame.
This fragment is called the pre-lude (or pre-amble) of the function.
+----------------------+ <------ Stack pointer (top of system stack) | Saved Frame Pointer | +----------------------+ | Return Address | +----------------------+ | 0 or more | | parameter variables | | | +----------------------+ | xxxxxx | +----------------------+ | yyyyyy | +----------------------+ | zzzzzz | +----------------------+ | ...... |
(you will see later that the saved frame pointer value will be used restored the frame pointer A6 to its original value when the called function returns to its caller function)
What we have built until now: What we want: +-----------------------+ <-- Stack | | pointer | | | | | | +----------------------+ <-- Stack +-----------------------+ <-- Frame | Saved Frame Pointer | Pointer | Saved Frame Pointer | pointer +----------------------+ +-----------------------+ | Return Address | | Return Address | +----------------------+ +-----------------------+ | 0 or more | | 0 or more | | parameter variables | | parameter variables | | | | | +----------------------+ +-----------------------+ | xxxxxx | | xxxxxx | +----------------------+ +-----------------------+ | yyyyyy | | yyyyyy | +----------------------+ +-----------------------+ | zzzzzz | | zzzzzz | +----------------------+ +-----------------------+ | ...... | | ...... |
MOVE.L A7, A6
+----------------------+ <------ Frame pointer and Stack pointer | Saved Frame Pointer | +----------------------+ | Return Address | +----------------------+ | 0 or more | | parameter variables | | | +----------------------+ | xxxxxx | +----------------------+ | yyyyyy | +----------------------+ | zzzzzz | +----------------------+ | ...... |
This is done by pushing the stack pointer further upwards and the resulting structure is:
+----------------------+ <------ Stack pointer (top of system stack) | 0 or more | | local variables | | | +----------------------+ <------ Frame pointer | Saved Frame Pointer | +----------------------+ | Return Address | +----------------------+ | 0 or more | | parameter variables | | | +----------------------+ | xxxxxx | +----------------------+ | yyyyyy | +----------------------+ | zzzzzz | +----------------------+ | ...... |Notice that the stack pointer and frame pointer are seperated. The stack pointer is used to "protect" the reserved memory spaces while the frame pointer is used to locate (access) the parameter and local variables.
You may (or may not) have notice that I quoted "protect" in the last sentence.
That is because the stack pointer itself cannot "protect" the reserved memory spaces.
It is up to the programmer to respect the reservation.
The stack pointer simply gives the limit of the memory space after which all location is reserved.
It is up to the programmer to respect this. If he does (no bugs), the reservation is honored. And if the programmer made an error and its program allocate some PREVIOUSLY reserved space AGAIN, then the protection is violated.
(It's somewhat comparable to a sign that says "No Trespassing" - it's up to the individual to honor this request or not. And just like the sign example, there are consequences if you do not honor the reservation.... Your program will usually crash and burn if you do not maintain the reservation correctly, since the memory location has been assigned for multiple use and multiple values will overwrite one another... It is not gonna be pretty to debug such a program either...)