I am allocating 12 char string on the st开发者_开发技巧ack, or equivalently it is 12 bytes.
Dissembling with gdb (under Linux) reveals that to allocate space for string on the stack, esp is moved by -24 (down the stack).
push %ebp
mov %esp,%ebp
sub $0x18,%esp
Why is it moved by 24 (0x18)?
Some of it could be space for outgoing parameters, if your function calls others; some of it could be temporary space for values spilled out of registers; some of it could be padding. It will be very dependent on compiler version and optimisation flags.
Here's some simple nonsense code for illustration:
extern int foo(int a, int b);
int bar(int c)
{
char s[12];
s[0] = foo(c, 123);
return 456;
}
Here it is compiled with no optimisation using gcc 4.3.2 on a Debian Lenny machine:
bar:
pushl %ebp
movl %esp, %ebp
subl $24, %esp
movl $123, 4(%esp)
movl 8(%ebp), %eax
movl %eax, (%esp)
call foo
movb %al, -12(%ebp)
movl $456, %eax
leave
ret
Like your code, it's allocating 24 bytes. Here's what they're used for:
Stack while running bar() : : +-------------------------+ | incoming parameter: c | 8(%ebp) +-------------------------+ --- | return address | 4(%ebp) ^ +-------------------------+ | | old %ebp | (%ebp) | +-------------------------+ | bar()'s stack | s[8]..s[11] | -4(%ebp) | frame: 32 bytes +-------------------------+ | | s[4]..s[7] | -8(%ebp) | +-------------------------+ | | s[0]..s[3] | -12(%ebp) | +-------------------------+ | Stack while running foo() | (unused) | 8(%esp) | : : +-------------------------+ | +-------------------------+ | outgoing parameter: 123 | 4(%esp) | | incoming parameter: b | +-------------------------+ | +-------------------------+ | outgoing parameter: c | (%esp) v | incoming parameter: a | +-------------------------+ --- +-------------------------+ | return address | +-------------------------+ | old %ebp | +-------------------------+ : locals for foo() :
A bit of experiment will show that if s[]
is increased, it will eat into the unused space; e.g. if it is 13 bytes, the stack frame is the same size, but s[]
will start one byte earlier (at -13(%ebp)
) - up to 16 bytes, where all of the allocated stack will actually be used. If s
is declared as s[17]
, the compiler will allocate 40 bytes of stack instead of 24.
This is because the compiler is keeping the total size of the stack frame (everything on the left of the above diagram, except the incoming parameter, which is really at the bottom of the caller's stack frame) rounded up to a multiple of 16 bytes. (See the gcc documentation for the -mpreferred-stack-boundary
option.)
Because other things besides your string are getting stored on the stack, such as other local variables or temporaries. When you have complicated expressions, the compiler stores sometimes stores intermediate results of those expressions in memory on the stack (especially when optimization is disabled), even if they don't correspond to explicit local variables.
精彩评论