x86汇编堆栈预留

时间:2012-03-05 11:25:33

标签: x86

考虑这个简单的C程序

#include <stdio.h>

int func()
{
    printf("Hello World\n");
    return 0;
}

int main()
{
    printf("Hello World\n");
    return 0;
}

这是由gcc

编译的相应32位程序集
    .file   "a.c"
        .section        .rodata
    .LC0:
        .string "Hello World"
        .text
    .globl func
        .type   func, @function
    func:
         pushl   %ebp
         movl    %esp, %ebp
         subl    $24, %esp
         movl    $.LC0, (%esp)
         call    puts
         movl    $0, %eax
         leave
         ret
         .size   func, .-func
    .globl main
         .type   main, @function
    main:
          pushl   %ebp
          movl    %esp, %ebp
          andl    $-16, %esp
          subl    $16, %esp
          movl    $.LC0, (%esp)
          call    puts
          movl    $0, %eax
          leave
          ret
          .size   main, .-main
          .ident  "GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3"
          .section        .note.GNU-stack,"",@progbits

为什么gcc为字符串保留24个字节&#34; Hello World&#34;在功能&#39; func()&#39;但主函数中只有16个字节用于相同的字符串?

1 个答案:

答案 0 :(得分:0)

编译器正试图为这两个函数分配16B(它是否需要那么多是有问题的。)

在“main”中,它只分配16B并调用puts。请注意,在调用之前,堆栈与0 mod 16对齐,因为这在ABI中是必需的(也就是说,在调用之前,堆栈总是0 mod 16)。

在func中,堆栈以12 mod 16对齐(由于返回地址)。然后我们推动ebp,使其成为8 mod 16.现在,我们想在堆栈上分配16B(类似于main),但我们也希望堆栈在调用put之前是0 mod 16字节对齐,因此,我们需要减去8 + 16个字节,即24。