|
We use a fixed pointer that points to a relatively fixed location in the stack and use this fixed pointer to access the parameters and local variables |
Answer: at the separation point between the parameters and local variables
+---------------+ <----- a7 (stack pointer) -8(a6) | s | Local variable +---------------+ -4(a6) | i | Local variable +---------------+ <----- a6 (frame pointer) 0(a6) | return address| +---------------+ 4(a6) | n (10) | Parameter +---------------+ 8(a6) | A (#A) | Parameter +---------------+ |
Offsets used to access variables BEFORE adding extra local variable | Offsets used to access variables AFTER adding extra local variable |
---|---|
+---------------+ <----- a7 -8(a6) | s | +---------------+ -4(a6) | i | +---------------+ <----- a6 0(a6) | return address| +---------------+ 4(a6) | n (10) | +---------------+ 8(a6) | A (#A) | +---------------+ |
+---------------+ <----- a7 -12(a6) | x | +---------------+ -8(a6) | s | +---------------+ -4(a6) | i | +---------------+ <----- a6 0(a6) | return address| +---------------+ 4(a6) | n (10) | +---------------+ 8(a6) | A (#A) | +---------------+ |
main: int A[10]; int sum; sum = ArraySum(A, 10); |
int ArraySum(int A[], int n) { int i, s; // Local variables s = 0; for (i = 0; i < n; i++) s = s + A[i]; return (s); } |
main: move.l #A, -(a7) * Pass address of array A move.l #10, -(a7) * Pass # elements in array bsr ArraySum adda.l #8, a7 * remove (pop) #A and #10 from stack move.l d0, sum * put return value in variable "sum" |
+---------------+ | free space | +---------------+ <----- a7 (stack pointer) 0(a7) | return address| +---------------+ 4(a7) | n (#10) | +---------------+ 8(a7) | A (#A) | +---------------+ | ..... | |
|
The subroutine returns the value in register D0.
********************************************************* * This version does NOT save A6 - we will fix it later * ********************************************************* ArraySum: movea.l a7, a6 * setup a6 !!! * The stack is: * * Offsets * +---------------+ <----- a6 and a7 (stack pointer) * 0(a6) | return address| * +---------------+ * 4(a6) | n (10) | * +---------------+ * 8(a6) | A (#A) | * +---------------+ suba.l #8, a7 * Create 2 local variables on stack !!! * NOW the stack is: * * Offsets * +---------------+ <----- a7 (stack pointer) * -8(a6) | s | (you decide which location is s and i) * +---------------+ (This program uses s and i in the given manner) * -4(a6) | i | * +---------------+ <----- a6 (frame pointer) * 0(a6) | return address| * +---------------+ * 4(a6) | n (10) | * +---------------+ * 8(a6) | A (#A) | * +---------------+ move.l #0, -8(a6) * s = 0 move.l #0, -4(a6) * i = 0 While: move.l -4(a6), d0 * puts local variable i in d0 move.l 4(a6), d1 * puts parameter n in d1 cmp.l d1, d0 BGE WhileEnd * Exit while loop if i >= n * ---- body of while loop movea.l 8(a6), a0 * put base address of array in A0 * (prepare to access A[i]) move.l -4(a6), d0 * now d0 = i muls #4, d0 * offset is now in d0 move.l (a0, d0.w), d0 * put A[i] in d0 add.l d0, -8(a6) * add A[i] to local variable s move.l -4(a6), d0 add.l #1, d0 move.l d0, -4(a6) * i = i + 1 BRA While WhileEnd: move.l -8(a6), d0 * Return s in the agreed location (d0) * The stack is STILL: * * Offsets * +---------------+ <----- a7 (stack pointer) * -8(a6) | s | * +---------------+ * -4(a6) | i | * +---------------+ <----- a6 (frame pointer) * 0(a6) | return address| * +---------------+ * 4(a6) | n (10) | * +---------------+ * 8(a6) | A (#A) | * +---------------+ * * If you return NOW, your program will NOT pop the return address * into the Program counter and it will CRASH !!! movea.l a6, a7 * NEW (better) way to remove local variables !!! * Better you don't need to know how many local * variables to remove !!! * NOW the stack is: * * +---------------+ <----- a7 (stack pointer) * | return address| * +---------------+ * | n (10) | * +---------------+ * | A (#A) | * +---------------+ * * NOW you can rexecute the return instruction !!! rts |
Therefore:
|
|
The subroutine returns the value in register D0.
ArraySum: movea.l a6, -(a7) ********** Save a6 from the caller subroutine !!!!!!!!! * The stack is now: * * +---------------+ <----- a7 (stack pointer) * | a6 from caller| * +---------------+ * | return address| * +---------------+ * | n (10) | * +---------------+ * | A (#A) | * +---------------+ movea.l a7, a6 * (setup a6 to access local vars and parameters) * The parameters can now be accessed through a6 as follows: * * Offsets * +---------------+ <----- a6 and a7 (stack pointer) * 0(a6) | a6 from caller| * +---------------+ * 4(a6) | return address| * +---------------+ * 8(a7) | n (10) | * +---------------+ * 12(a7) | A (#A) | * +---------------+ suba.l #8, a7 * Create 2 local variables on stack !!! * NOW the stack is (along with offsets on how to access local variables): * * Offsets * +---------------+ <----- a7 (stack pointer) * -8(a6) | s | (you decide which location is s and i) * +---------------+ (This program uses s and i in the given manner) * -4(a6) | i | * +---------------+ <----- a6 (frame pointer) * 0(a6) | a6 from caller| * +---------------+ * 4(a6) | return address| * +---------------+ * 8(a6) | n (10) | * +---------------+ * 12(a6) | A (#A) | * +---------------+ move.l #0, -8(a6) * s = 0 move.l #0, -4(a6) * i = 0 While: move.l -4(a6), d0 * puts local variable i in d0 move.l 8(a6), d1 * puts parameter n in d1 cmp.l d1, d0 BGE WhileEnd * Exit while loop if i >= n * ---- body of while loop movea.l 12(a6), a0 * put base address of array in A0 * (prepare to access A[i]) move.l -4(a6), d0 * now d0 = i muls #4, d0 * offset is now in d0 move.l (a0, d0.w), d0 * put A[i] in d0 add.l d0, -8(a6) * add A[i] to local variable s move.l -4(a6), d0 add.l #1, d0 move.l d0, -4(a6) * i = i + 1 BRA While WhileEnd: move.l -8(a6), d0 * Return s in the agreed location (d0) * The stack is STILL: * * Offsets * +---------------+ <----- a7 (stack pointer) * -8(a6) | s | * +---------------+ * -4(a6) | i | * +---------------+ <----- a6 (frame pointer) * 0(a6) | a6 from caller| * +---------------+ * 4(a6) | return address| * +---------------+ * 8(a6) | n (10) | * +---------------+ * 12(a6) | A (#A) | * +---------------+ * * If you return NOW, your program will NOT pop the return address * into the Program counter and it will CRASH !!! movea.l a6, a7 * Remove the local variables. * NOW the stack is: * * +---------------+ <----- a7 (stack pointer) * | a6 from caller| * +---------------+ * | return address| * +---------------+ * | n (10) | * +---------------+ * | A (#A) | * +---------------+ * * NOW is the time to recover the a6 value for the caller subroutine !!! movea.l (a7)+, a6 ***************** restore a6 !!!!!!!!!!!! * (The (a7)+ address mode is explained below) * NOW the stack is: * * +---------------+ <----- a7 (stack pointer) * | return address| * +---------------+ * | n (10) | * +---------------+ * | A (#A) | * +---------------+ * * NOW you can rexecute the return instruction !!! rts |
move.l (a7)+, <ea> is same as: move.l (a7), <ea> adda.l #4, a7 move.w (a7)+, <ea> is same as: move.w (a7), <ea> adda.l #2, a7 |