为什么在用 arm-linux-gnueabi-gcc 编译时堆栈指针向下移动 4 个字节比堆栈帧大小大? [英] Why is the stack pointer moved down 4 bytes greater than the stack frame size when compiling with arm-linux-gnueabi-gcc?
问题描述
以下面的简单 C 程序为例.main() 对传入 4 个整数的 sum 进行函数调用.sum() 使用 4 个局部变量.
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;
}
在我的 Ubuntu 服务器 12.04.04 LTS 上,我使用
On my Ubuntu server 12.04.04 LTS I compile this program using
arm-linux-gnueabi-gcc -S -mthumb func.c
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
看来 int 每个是 4 个字节.该函数的 4 个局部变量和 4 个参数总共是 (4 * 4 字节) + (4 * 4 字节) = 32 字节,这与汇编输出frame = 32"相匹配.
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".
但是为什么堆栈指针会减少 36 而不仅仅是 32?
But why does the stack pointer get decremented by 36 and not just 32?
推荐答案
ARM的过程调用标准要求8字节对齐.
Procedure call standard for ARM requires 8 byte alignment.
5.2.1.2 公共接口上的堆栈约束
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.堆栈必须双字对齐.
由于您正在生成程序集,因此默认情况下所有内容都导出,因此您可以获得 8 字节对齐.(我尝试了此操作,但 gcc 没有添加 .global <symbol>
生成程序集时对静态函数的指令.我猜这说明即使是静态函数也是一个公共接口,或者 gcc 只是将每个函数对齐为 8 字节堆栈对齐.)
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.)
你可以使用 -fomit-frame-pointer
跳过推送 r7
然后 gcc 应该将堆栈深度保留为 32.
You can use -fomit-frame-pointer
to skip pushing r7
then gcc should leave the stack depth at 32.
这篇关于为什么在用 arm-linux-gnueabi-gcc 编译时堆栈指针向下移动 4 个字节比堆栈帧大小大?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!