我不知道我的標題是否合適,導致我的問題是:我知道有時候(當我想使用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