2014-04-10 52 views
0

我的C代碼:無法設置堆棧邊界GCC

#include <stdio.h> 

foo() 
{ 
    char buffer[8]; 
} 

main() 
{ 
    foo(); 
    return 0; 
} 

我把它用gcc -ggdb -mpreferred-stack-boundary=2 -o bar bar.c

當我用它加載GDB ./bar我看到foo的函數裏面的代碼是編譯:

sub $0x0c,$esp 

這是怎麼發生的?

我想要在堆棧中緩衝8個字節,所以它應該是sub $0x8,$esp

爲什麼我不能將堆棧邊界設置爲4個字節?

幫助!

+0

首先確保它是0xC,而不是0xC0。無論如何,這兩種方式都與其所提供的4個已完成的堆棧邊界相一致。函數可能需要比局部變量總和更多的堆棧,例如對於臨時數據和例如用於將數據傳遞給其他功能。 – nos

+0

0xC0!= 0x0C ... –

+0

但爲什麼它沒有執行子$ 0x8,$ esp – user3270649

回答

0

我無法準確再現您所看到的內容,但是在我的4.8.2版本的gcc中,該選項會影響此代碼使用的堆棧數量(請確保使用「緩衝區」來避免它被優化遠,並定爲沒有返回類型/參數類型的警告):

#include <stdio.h> 

void foo(void) 
{ 
    char buffer[8]; 
    buffer[0] = 'a'; 
    buffer[1] = '\n'; 
    buffer[2] = 0; 
    printf("my first program! %s\n", buffer); 
} 

int main() 
{ 
    foo(); 
    return 0; 
} 

與-mpreferred堆疊邊界= 2和-mpreferred堆疊邊界= 4,並且將所生成的彙編程序之間的差異是編譯值得注意的是:

$ diff -u stb-2.s stb-4.s 
--- stb-2.s 2014-04-10 09:00:39.546038191 +0100 
+++ stb-4.s 2014-04-10 09:00:58.895108979 +0100 
@@ -15,11 +15,11 @@ 
    .cfi_offset 5, -8 
    movl %esp, %ebp 
    .cfi_def_cfa_register 5 
- subl $16, %esp 
- movb $97, -8(%ebp) 
- movb $10, -7(%ebp) 
- movb $0, -6(%ebp) 
- leal -8(%ebp), %eax 
+ subl $40, %esp 
+ movb $97, -16(%ebp) 
+ movb $10, -15(%ebp) 
+ movb $0, -14(%ebp) 
+ leal -16(%ebp), %eax 
    movl %eax, 4(%esp) 
    movl $.LC0, (%esp) 
.LEHB0: 
@@ -67,9 +67,10 @@ 
    .cfi_offset 5, -8 
    movl %esp, %ebp 
    .cfi_def_cfa_register 5 
+ andl $-16, %esp 
    call _Z3foov 
    movl $0, %eax 
- popl %ebp 
+ leave 
    .cfi_restore 5 
    .cfi_def_cfa 4, 4 
    ret 

所以,至少在gcc中是4.8.2。對於x86-32,該選項有效。

當然,根據文檔的默認值是-mpreferred-stack-boundary = 2,所以也許這就是爲什麼你看不到「沒有」的任何區別(雖然在我的實驗中,它似乎是-mpreferred -stack邊界= 4)。 [瞬間通過]啊,默認值已經隨時間而改變了,所以4.4.2文檔在線說2,我的信息gcc爲4.8.2說了4,這就解釋了差異。

至於爲什麼你的代碼是分配12個字節的堆棧空間 - 看的printf怎麼叫:

movl $.LC0, (%esp) 
call printf 

如果編譯器,它會預先分配參數空間功能在開始通話的功能,而不是像在這種情況下那樣使用push $.LC0。這並沒有太大的區別,但它至少在printf的另一端至少節省了一條清理指令(這使得在生成的代碼中處理堆棧相對偏移更容易,因爲編譯器不必跟蹤當前堆棧指針所在的位置 - 它始終位於函數開頭的序言代碼之後的一個恆定位置,一直到函數結尾)。由於無論如何都最終需要空間,因此「節省4個字節」毫無意義。