繁体   English   中英

从 x86_64 程序集调用 memset

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM