2014-03-25 26 views
2

我試圖通過查看從clang生成的程序集來學習x86程序集。例如,我想了解C中的自動數組是如何初始化爲全0的。從x86_64程序集調用memset

int64_t my_array [3000] = {0}; 

它看起來像程序集保留堆棧(3000 * 64b/8B/b)24000B然後調用memset。從memset的的手冊頁,它的簽名如下所示:

void * 
memset(void *b, int c, size_t len); 

所以我知道,第二個參數應該%RSI傳遞爲0,第三個參數(我想每個字節的值設置爲)(%RDX )爲24000美元,但第一個參數(%rdi)呢?從生成的程序集的兩個相關的指令看起來是:

leaq -24016(%rbp), %rax 
movq %rax, %rdi 

但我不明白爲什麼從基指針負24016?爲什麼要存儲在%rax中,然後立即移動到%rdi(也許是因爲我沒有編譯優化)?

無論哪種方式,我不知道如何將數組的第一個字節的地址傳遞給memset。我也在OSX上,所以我已經不得不通過8B來抵消我的堆棧指針來組裝。

回答

2

您已在堆棧(自動存儲)上分配了my_array,這意味着編譯器必須通過局部變量的大小加上空間來減少堆棧指針(堆棧向低地址增長)以保存寄存器等。 %ebp基指針被設置爲指向調用者的幀指針(在將調用者的基指針保存在堆棧上之後)。這是正確堆疊放卷所必需的約定的一部分。請參閱第9章異常處理和堆棧展開 Agner Fog全面的調用約定文檔

http://www.agner.org/optimize/calling_conventions.pdf

由於%ebp指向調用者的框架,編譯器使用它的負偏移指向my_array(被調用函數中的局部變量)的開始。

我沒有一個答案,爲什麼編譯存儲的地址%rax並立即複製它%rdi,似乎它可以這樣做,是在一個步驟

leaq -24016(%rbp), %rdi 
+0

我不明白-24016部分雖然,似乎任意。因爲堆棧向內存地址越來越低,所以負數是24000,因此我需要多少*,但爲什麼多餘的16B? %ebp是32b所以只需要4B? –

+1

請參閱第5章*堆棧對齊*在同一文檔中,它說:「64位系統將堆棧對齊16位。堆棧字大小爲8個字節,但在任何調用指令之前堆棧必須對齊16位。一個程序在存儲需要16字節對齊的XMM數據時可以依賴這些規則,這適用於所有64位系統(Windows,Linux,BSD)。 – amdn

+1

對,謝謝!看起來我有一些閱讀要做! –