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