%sp --------> +-----------------------+ | save %l0 | 8 local registers %sp + 4 ----> +-----------------------+ | save %l1 | (parameters to subroutine) %sp + 8 ----> +-----------------------+ | ......... | | ......... | | ......... | %sp + 32 ---> +-----------------------+ | save %i0 | 8 input registers %sp + 36 ---> +-----------------------+ | save %i1 | (local variables of subroutine) %sp + 40 ---> +-----------------------+ | ......... | | ......... | | ......... | %sp + 64 ---> +-----------------------+ | structure pointer !! | for a function that returns struct %sp + 68 ---> +-----------------------+ | save %o0 | 6 output registers: o0 - o5 %sp + 72 ---> +-----------------------+ | save %o1 | %sp + 76 ---> +-----------------------+ | ......... | | ......... | %sp + 88 ---> +-----------------------+ | save %o5 | %sp + 92 ---> +-----------------------+ 92 is NOT divisible by 8 | ???????? | Will be explained later... %sp + 96 ---> +-----------------------+ 96 is divisible by 8 |
Then the Operating System will use the space intended for the parameter to save the local registers !!!
Run the program in EGTAPI.
Make a note of the stack when SPARC reaches the instruction "add %sp, -8, %sp".
Now that you know what the cause of the problem is, solving it is a lot easier !!!
int B( int p1, int p2, int p3, int p4, int p5, int p6, int p7, int p8, int p9, int p10) { ... } void A() { int x; x = B( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ); } |
Then the prelude (beginning) of the function A must allocate 16 (4 x 4) additional bytes
92 + 16 = 108 is NOT divisible by 8.
So we add 4 more bytes for padding
A: save %sp, -(92 + 16 + 4), %sp ... ... ... ret restore |
In other words:
MEMORY %sp --------> +-----------------------+ | save %l0 | 8 local registers %sp + 4 ----> +-----------------------+ | save %l1 | (parameters to subroutine) %sp + 8 ----> +-----------------------+ | ......... | | ......... | | ......... | %sp + 32 ---> +-----------------------+ | save %i0 | 8 input registers %sp + 36 ---> +-----------------------+ | save %i1 | (local variables of subroutine) %sp + 40 ---> +-----------------------+ | ......... | | ......... | | ......... | %sp + 64 ---> +-----------------------+ | structure pointer !! | for a function that returns struct %sp + 68 ---> +-----------------------+ | save %o0 | 6 output registers: o0 - o5 %sp + 72 ---> +-----------------------+ | save %o1 | %sp + 76 ---> +-----------------------+ | ......... | | ......... | %sp + 88 ---> +-----------------------+ | save %o5 | %sp + 92 ---> +-----------------------+ | param 7 | %sp + 96 ---> +-----------------------+ | param 8 | %sp + 100 --> +-----------------------+ | param 9 | %sp + 104 --> +-----------------------+ | param 10 | --> +-----------------------+ | ... | --> +-----------------------+ <--- %fp - 4 | possible local vars | --> +-----------------------+ <--- %fp |
Since this location is fixed (OK, the location is somewhat strange, but something gotta give... :-)), we have obtained a workable solution to pass additional parameters.
parameter 7 st ..., [%sp + 92] parameter 8 st ..., [%sp + 96] parameter 9 st ..., [%sp + 100] parameter 10 st ..., [%sp + 104] |
MEMORY %sp --------> +-----------------------+ | save %l0 | This is B's stack frame !!! %sp + 4 ----> +-----------------------+ | save %l1 | %sp + 8 ----> +-----------------------+ | ......... | | ......... | | ......... | | ......... | | ......... | %fp --------> +-----------------------+ | save %l0 | This is A's stack frame !!! %fp + 4 ----> +-----------------------+ | save %l1 | %fp + 8 ----> +-----------------------+ | ......... | | ......... | | ......... | %fp + 32 ---> +-----------------------+ | save %i0 | 8 input registers %fp + 36 ---> +-----------------------+ | save %i1 | (local variables of subroutine) %fp + 40 ---> +-----------------------+ | ......... | | ......... | | ......... | %fp + 64 ---> +-----------------------+ | structure pointer !! | for a function that returns struct %fp + 68 ---> +-----------------------+ | save %o0 | 6 output registers: o0 - o5 %fp + 72 ---> +-----------------------+ | save %o1 | %fp + 76 ---> +-----------------------+ | ......... | | ......... | %fp + 88 ---> +-----------------------+ | save %o5 | %fp + 92 ---> +-----------------------+ | param 7 | %fp + 96 ---> +-----------------------+ | param 8 | %fp + 100 --> +-----------------------+ | param 9 | %fp + 104 --> +-----------------------+ | param 10 | --> +-----------------------+ | ... | --> +-----------------------+ | A's local vars | (B shoul NOT touch A's locals) --> +-----------------------+ |
parameter 1 in register %i0 parameter 2 in register %i1 parameter 3 in register %i2 parameter 4 in register %i3 parameter 5 in register %i4 parameter 6 in register %i5 parameter 7 in stack at address [%fp + 92] parameter 8 in stack at address [%fp + 96] parameter 9 in stack at address [%fp + 100] parameter 10 in stack at address [%fp + 104] |
Compile it with:
Run it inside EGTAPI. Scroll the stack area down to the bottom and you will see how the additional parameters are passed.