int fib(int n) { if (n = 0) return 1; else if (n == 1) return 1; else { return fib(n-1) + fib(n-2); } } |
int n, result; result = fib(n); |
|
Therefore, the main program must pass the parameter n to Fibonacci by pushing n onto the system stack:
move.l n, -(a7) |
This instruction will create the following stack structure:
+---------------------+ <------------ Stack pointer (A7) | parameter n | +---------------------+ | ....... | | rest of the stack | | ....... | |
bsr fib |
This will push the return address on the stack and create the following stack structure:
+---------------------+ <------------ Stack pointer (A7) | return address | +---------------------+ | parameter n | +---------------------+ | ....... | | rest of the stack | | ....... | |
int fib(int n)
{
if (n = 0)
return 1;
else if (n == 1)
return 1;
else
{
return fib(n-1) + fib(n-2);
}
}
|
You will notice that there are two (recursive) calls to Fibonacci.
|
|
Conclussion:
|
Where is a safe place in recursive programming:
|
Therefore:
|
********************************* PRELUDE move.l a6, -(a7) ; Save caller's frame pointer move.l a7, a6 ; Setup my own frame pointer suba.l #4, a7 ; Allocate space for local variable for fib(n-1) ********************************* |
I will explain what each one does below. Make sure that you realise that the structure of the stack frame is like this when the prelude is always executed:
+---------------------+ <------------ Stack pointer (A7) | return address | +---------------------+ | parameter n | +---------------------+ | ....... | | rest of the stack | | ....... |
This will save the frame pointer on the stack, creating this partial stack frame structure:
+---------------------+ <------------ Stack pointer (A7) | saved a6 | +---------------------+ | return address | +---------------------+ | parameter n | +---------------------+ | ....... | | rest of the stack | | ....... |
This will make the frame pointer A6 points to the stack frame that is now being built:
+---------------------+ <---- Frame pointer A6 & Stack pointer (A7) | saved a6 | point to the same location.... +---------------------+ | return address | +---------------------+ | parameter n | +---------------------+ | ....... | | rest of the stack | | ....... |
This will push the stack pointer A7 4 bytes up, allocating 1 integer variables -- used to save the return value of fib(n-1).
+---------------------+ <---- Stack pointer (A7) | help (local var)| +---------------------+ <---- Frame pointer (A6) | saved a6 | +---------------------+ | return address | +---------------------+ | parameter n | +---------------------+ | ....... | | rest of the stack | | ....... |
|
|
|
Make sure you pop the parameter from the stack after Fibonacci returns - because the parameter has not been cleaned up.
The following is the program fragment where Fibonacci calls fib(n-1):
move.l 8(a6), d0 ; retrieve parameter n into register d0 sub.l #1, d0 ; d0 = n - 1 * * ----------------------------- ; fib is calling fib now !!!! * move.l d0, -(a7) ; Push (n-1) as parameter bsr fib ; Call fib(n-1) adda.l #4,a7 ; Clean up parameter from stack move.l d0, -4(a6) ; help = return value of fib(n-1) in register D0 |
Fibonacci will call itself a second time with value n-2. The following is the program fragment where Fibonacci calls fib(n-2):
move.l 8(a6), d0 ; retrieve parameter n into register d0 sub.l #2, d0 ; d0 = n - 2 * * ----------------------------- ; fib is calling fib again.... * move.l d0, -(a7) ; Push (n-2) as parameter bsr fib ; Call fib(n-2) adda.l #4,a7 ; Clean up parameter from stack add.l -4(a6),d0 ; Compute the value: fib(n-1)+fib(n-2) |
I have highlighted the difference between the first call and the second. The second call uses a different parameter value and stores the return value in a different local variable !
* =============================================== * main: result = fib(n) * =============================================== Start: movea.l #12345,a6 ; Store something in a6 to make it dramatic move.l n,-(a7) ; Call fib(n) bsr fib adda.l #4,a7 ; pop parameter off the stack move.l d0,result ; result = return value Stop: nop n: dc.l 5 ; variable n (input) result: ds.l 1 ; variable result (output) * ========================================================= Fib * int fib(int n) * { * if (n = 0) * return 1; * else if (n == 1) * return 1; * else * { * return fib(n-1) + fib(n-2); * } * } * * ---------------------------------------------------- * Input: n on stack * Output: fib(n) in register d0 fib: ********************************* PRELUDE move.l a6,-(a7) ; Save caller's frame pointer move.l a7,a6 ; Setup my own frame pointer suba.l #4,a7 ; Allocate space for local var. "help" ********************************* * Start of function.... move.l 8(a6),d0 ; n cmp.l #0,d0 ; n == 0 ? bne else1 move.l #1,d0 ; return(1) ********************************* POSTLUDE move.l a6,a7 ; Deallocate local variable(s) move.l (a7)+,a6 ; restore caller's frame pointer ********************************* rts else1: move.l 8(a6),d0 ; n cmp.l #1,d0 ; n == 1 ? bne else2 move.l #1,d0 ; return(1) ********************************* POSTLUDE move.l a6,a7 ; Deallocate local variable(s) move.l (a7)+,a6 ; restore caller's frame pointer ********************************* rts else2: ********************************* fib(n-1) move.l 8(a6),d0 ; n sub.l #1,d0 ; n - 1 move.l d0,-(a7) ; Push (n-1) bsr fib ; call fib(n-1) - will return to next instruction adda.l #4,a7 ; Clean up: Pop parameter (n-1) from stack move.l d0,-4(a6) ; Save return value (fib(n-1)) in local var !! ********************************* compute fib(n-2) move.l 8(a6),d0 ; n sub.l #2,d0 ; n - 2 move.l d0,-(a7) ; Push (n-2) bsr fib ; call fib(n-2) - will return to next instruction adda.l #4,a7 ; Clean up: Pop parameter (n-2) from stack ********** add.l -4(a6),d0 ; Compute the return value: fib(n-1)+fib(n-2) ********************************* POSTLUDE move.l a6,a7 ; Deallocate local variable(s) move.l (a7)+,a6 ; restore caller's frame pointer ********************************* rts End: end |
How to run the program:
|