[英]Why does calling the C abort() function from an x86_64 assembly function lead to segmentation fault (SIGSEGV) instead of an abort signal?
[英]calling memset from x86_64 assembly
我正在嘗試通過查看從 clang 生成的程序集來學習 x86 程序集。 例如,我想了解 C 中的自動數組如何初始化為全 0。
int64_t my_array [3000] = {0};
看起來程序集在堆棧上保留 24000B ( 3000 * 64b / 8B/b ) 然后調用 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 才能組裝。
您已在堆棧(自動存儲)上分配了my_array
,這意味着編譯器必須將堆棧指針(堆棧向低地址增長)遞減為局部變量的大小加上用於保存寄存器等的空間。 %ebp
基指針被設置為指向調用者的幀指針(在通過將調用者的基指針壓入堆棧來保存調用者的基指針之后)。 這是正確堆棧展開所需的約定的一部分。 請參閱 Agner Fog 的綜合調用約定文檔中的第 9 章異常處理和堆棧展開
http://www.agner.org/optimize/calling_conventions.pdf 。
由於%ebp
指向調用者的幀,編譯器使用它的負偏移量指向my_array
的開頭,這是被調用函數中的局部變量。
我不知道為什么編譯器將地址存儲在%rax
並立即將其復制到%rdi
,似乎可以一步完成
leaq -24016(%rbp), %rdi
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.