I was playing around a bit to get a better grip on calling conventions and how the stack is handled, but I can't figure out why main allocates three extra double words when setting up the stack (at <main+0>
). It's neither aligned to 8 bytes nor 16 bytes, so that's not why as far as I know. As I see it, main requires 12 bytes for the two parameters to func and the return value.
What am I missing?
The program is C code compiled with "gcc -ggdb" on a x86 architecture.
Edit: I removed the -O0 flag from gcc, and it made no difference to the output.
(gdb) disas main
Dump of assembler code for function main:
0x080483d1 <+0>: sub esp,0x18
0x080483d4 <+3>: mov DWORD PTR [esp+0x4],0x7
0x080483dc <+11>: mov DWORD PTR [esp],0x3
0x080483e3 <+18>: call 0x80483b4 <func>
0x080483e8 <+23>: mov DWORD PTR [esp+0x14],eax
0x080483ec <+27>: add esp,0x18
0x080483ef <+30>: ret
End of assembler dump.
Edit: Of course I should have posted the C code:
int func(int a, int b) {
int c = 9;
return a + b + c;
}
void main() {
int x;
x = func(3, 7);
}
The platform is Arch Linux i686.
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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With