c - 调用 glibc 时的 x86-64 ELF 初始堆栈布局

标签 c assembly x86-64 nasm glibc

基本上,我通读了 http://www.nasm.us/links/unix64abi 的部分内容在第 29 页,它显示了 C 程序的初始进程堆栈。

我的问题是:我正在尝试与 x86-64 nasm 中的 glibc 交互,根据上面显示的内容,argc 应该位于 rsp。所以下面的代码应该打印 argc:

[SECTION .data]
PrintStr: db "You just entered %d arguments.", 10, 0

[SECTION .bss]

[SECTION .text]
extern printf
global main

main:
     mov rax, 0        ; Required for functions taking in variable no. of args
     mov rdi, PrintStr
     mov rsi, [rsp]
     call printf
     ret

但事实并非如此。如果我的代码有任何错误,有人可以启发我,或者告诉我实际的堆栈结构是什么吗?

谢谢!

更新:我只是随机尝试了一些偏移量并将“mov rsi, [rsp]”更改为“mov rsi, [rsp+28]”就成功了。

但这意味着显示的堆栈结构是错误的。有谁知道 x86-64 elf 的初始堆栈布局是什么?相当于 http://asm.sourceforge.net/articles/startup.html会非常好。

更新 2: 我省略了如何构建此代码。我这样做:

nasm -f elf64 -g <filename>
gcc <filename>.o -o <outputfile>

最佳答案

初始堆栈布局在堆栈指针处包含argc,然后是数组 char *argv[],而不是指向它的指针就像 main 收到的那样。因此,要调用 main,您需要执行如下操作:

pop %rdi
mov %rsp,%rsi
call main

实际上通常有一个调用main 的包装函数,而不是直接在启动代码中调用。

如果你只想打印argv[0],你可以这样做:

pop %rdi
pop %rdi
call puts
xor %edi,%edi
jmp exit

关于c - 调用 glibc 时的 x86-64 ELF 初始堆栈布局,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5842001/

相关文章:

c - 如何使用 union (位字段)处理自定义浮点?

c - K&R 练习 1-18 几乎完成...为什么我在某些行的末尾出现奇怪的字符?

c - C结构如何传递给汇编函数?

performance - 我如何从预取内在函数中获得可衡量的好处?

c - poll/select 和 writefds 的最佳实践

c - 在 C 中的数据类型之前使用宏

c - 如何根据汇编中的地址调用printf函数

macos - 为什么 `write()`是通过 `call`指令而不是中断来执行的?

c++ - 调用但不跳转到 rax 中的地址时出现段错误

linux-kernel - 为什么 x86-64 Linux 系统调用使用 6 个寄存器集工作?