问题
Using the trivial C program below as an example. main() makes a function call to sum passing in 4 integer. sum() uses 4 locals.
void sum(int a, int b, int c, int d);
void main(void)
{
sum(11, 12, 13, 14);
}
void sum(int a, int b, int c, int d)
{
int x;
int y;
int z;
int z2;
x = a;
y = b;
z = c;
z2 = d;
}
On my Ubuntu server 12.04.04 LTS I compile this program using
arm-linux-gnueabi-gcc -S -mthumb func.c
sum:
@ args = 0, pretend = 0, frame = 32
@ frame_needed = 1, uses_anonymous_args = 0
@ link register save eliminated.
push {r7}
sub sp, sp, #36 <=== why is this 36 and not 32 bytes?
add r7, sp, #0
str r0, [r7, #12]
str r1, [r7, #8]
str r2, [r7, #4]
str r3, [r7, #0] <- paramaters passed
ldr r3, [r7, #12]
str r3, [r7, #16] <- locals
ldr r3, [r7, #8]
str r3, [r7, #20]
ldr r3, [r7, #4]
str r3, [r7, #24]
ldr r3, [r7, #0]
str r3, [r7, #28]
add r7, r7, #36
mov sp, r7
pop {r7}
bx lr
It appears that int's a 4 bytes each. 4 locals and 4 arguments for the function makes a total of (4 *4 bytes) + (4 * 4bytes) = 32 bytes and this matches the assembly output "frame = 32".
But why does the stack pointer get decremented by 36 and not just 32?
回答1:
Procedure call standard for ARM requires 8 byte alignment.
5.2.1.2 Stack constraints at a public interface
The stack must also conform to the following constraint at a public interface:
- SP mod 8 = 0. The stack must be double-word aligned.
Since you are producing assembly everything is exported by default, so you get 8 byte alignment. (I tried this and gcc doesn't add .global <symbol>
directive to static functions when generating assembly. I guess this says even a static function is a public interface or gcc just aligns every function to have 8-byte stack alignment.)
You can use -fomit-frame-pointer
to skip pushing r7
then gcc should leave the stack depth at 32.
来源:https://stackoverflow.com/questions/22279911/why-is-the-stack-pointer-moved-down-4-bytes-greater-than-the-stack-frame-size-wh