为什么在用 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?

查看:30
本文介绍了为什么在用 arm-linux-gnueabi-gcc 编译时堆栈指针向下移动 4 个字节比堆栈帧大小大?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下面的简单 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆