First of all, the x86 stack grows downwards. By convention, rbp
stores the original value of rsp
. Therefore, the function's arguments reside at positive offsets relative to rbp
, and its automatic variables reside at negative offsets. The first element of an automatic array has a lower address than all other elements, and thus is the furthest away from rbp
.
Here is a handy diagram that appears on this page:
I see no reason why the compiler couldn't use a series of push
instructions to initialize your array. Whether this would be a good idea, I am not sure.
The parameters to a function (including, but not limited to main
) are already on the stack when you enter the function. The space you allocate inside the function is for local variables. For functions with simple return types such as int
, the return value will normally be in a register (eax
, with a typical 32-bit compiler on x86).
If, for example, main
was something like this:
int main(int argc, char **argv) {
char a[35];
return 0;
}
...we'd expect to see at least 35 bytes allocated on the stack as we entered main to make room for a
. Assuming a 32-bit implementation, that would normally be rounded up to the next multiple of 4 (36, in this case) to maintain 32-bit alignment of the stack. We would not expect to see any space allocated for the return value. argc
and argv
would be on the stack, but they'd already be on the stack before main
was entered, so main
would not have to do anything to allocate space for them.
In the case above, after allocating space for a
, a
would typicaly start at [esp-36]
, argv
would be at [esp-44]
and argc
would be at [esp-48]
(or those two might be reversed -- depending on whether arguments were pushed left to right or right to left). In case you're wondering why I skipped [esp-40]
, that would be the return address.
Edit: Here's a diagram of the stack on entry to the function, and after setting up the stack frame:
Edit 2: Based on your updated question, what you have is slightly roundabout, but not particularly hard to understand. Upon entry to main
, it's allocating space not only for the variables local to main
, but also for the parameters you're passing to the function you call from main
.
That accounts for at least some of the extra space being allocated (though not necessarily all of it).
Best Answer
I've had a go at it: