我不知道我的标题是否合适,导致我的问题是:我知道有时候(当我想使用argv []时,编译器必须安排空间命令行参数的堆栈。现在我编写了一个简单的程序来看看C编译器如何处理简单的C数组(实际上它的处理方式与std::array
相同)。我正在使用Manjaro Linux 64位。 C代码看起来是这样的:为什么编译器在堆栈上创建空间
#include <stdio.h>
int main(){
int a[5] = {1,2,3,4,5};
//printf("%d", a[1]);
return 0;
}
的组件产生的输出(来自gcc main.c -fno-asynchronous-unwind-tables -o XD.s -S
):
.file "main.c"
.text
.globl main
.type main, @function
main:
pushq %rbp
movq %rsp, %rbp
movl $1, -32(%rbp)
movl $2, -28(%rbp)
movl $3, -24(%rbp)
movl $4, -20(%rbp)
movl $5, -16(%rbp)
movl $0, %eax
popq %rbp
ret
.size main, .-main
.ident "GCC: (GNU) 6.3.1 20170109"
.section .note.GNU-stack,"",@progbits
现在,当我取消printf
声明,代码如下所示:
.file "main.c"
.section .rodata
.LC0:
.string "%d"
.text
.globl main
.type main, @function
main:
pushq %rbp
movq %rsp, %rbp
subq $32, %rsp
movl $1, -32(%rbp)
movl $2, -28(%rbp)
movl $3, -24(%rbp)
movl $4, -20(%rbp)
movl $5, -16(%rbp)
movl -28(%rbp), %eax
movl %eax, %esi
movl $.LC0, %edi
movl $0, %eax
call printf
movl $0, %eax
leave
ret
.size main, .-main
.ident "GCC: (GNU) 6.3.1 20170109"
.section .note.GNU-stack,"",@progbits
中间部分很明显,只叫printf
。但为什么编译器在这里放置了一条subq $32, %rsp
行?为什么不出现在第一个例子中,没有printf
声明?
我不认为打开优化检查生成的代码是没有任何价值的。 – DeiDei
可能$ 32意味着ASCII'2',它只是硬编码这个值而不是计算它?你已经启用了哪些优化? – Lundin
“为什么不出现在第一个示例中,没有printf语句?”它不必,因为它是(堆栈式)最深的功能。调用printf的版本必须保存堆栈,因为printf本身会禁止它。但DeiDei的未经优化的代码没有经过优化,在 – Tommylee2k