小编Dav*_*vid的帖子

堆栈分配,填充和对齐

我一直在努力深入了解编译器如何生成机器代码,更具体地说是GCC如何处理堆栈.在这样做的过程中,我一直在编写简单的C程序,将它们编译成汇编并尽力理解结果.这是一个简单的程序及其生成的输出:

asmtest.c:

void main() {
    char buffer[5];
}
Run Code Online (Sandbox Code Playgroud)

asmtest.s:

pushl   %ebp
movl    %esp, %ebp
subl    $24, %esp
leave
ret
Run Code Online (Sandbox Code Playgroud)

让我感到困惑的是为什么要为堆栈分配24个字节.我知道由于处理器如何寻址内存,堆栈必须以4为增量进行分配,但如果是这种情况,我们应该只将堆栈指针移动8个字节而不是24个.作为参考,缓冲区为17 bytes产生一个移动40个字节的堆栈指针,并且根本没有缓冲区移动堆栈指针8. 1到16个字节之间的缓冲区移动ESP24个字节.

现在假设8个字节是必要的常量(它需要什么?),这意味着我们分配16个字节的块.为什么编译器会以这种方式对齐?我正在使用x86_64处理器,但即使是64位字也只需要8字节对齐.为什么会出现差异?

作为参考,我正在使用gcc 4.0.1运行10.5的Mac上进行编译,并且未启用任何优化.

c x86 assembly stack gcc

45
推荐指数
2
解决办法
2万
查看次数

堆栈上的局部变量分配顺序

看看这两个功能:

void function1() {
    int x;
    int y;
    int z;
    int *ret;
}

void function2() {
    char buffer1[4];
    char buffer2[4];
    char buffer3[4];
    int *ret;
}
Run Code Online (Sandbox Code Playgroud)

如果我打破function1()gdb,并打印变量的地址,我得到这个:

(gdb) p &x  
$1 = (int *) 0xbffff380
(gdb) p &y
$2 = (int *) 0xbffff384
(gdb) p &z
$3 = (int *) 0xbffff388
(gdb) p &ret
$4 = (int **) 0xbffff38c
Run Code Online (Sandbox Code Playgroud)

如果我做同样的事情function2(),我得到这个:

(gdb) p &buffer1
$1 = (char (*)[4]) 0xbffff388
(gdb) p &buffer2
$2 = (char (*)[4]) …
Run Code Online (Sandbox Code Playgroud)

c memory x86 stack gcc

26
推荐指数
4
解决办法
2万
查看次数

标签 统计

c ×2

gcc ×2

stack ×2

x86 ×2

assembly ×1

memory ×1