![](/img/trans.png)
[英]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.