|
| 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
|