考虑这个简单的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个字节用于相同的字符串?
答案 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。