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

时间:2011-04-30 13:19:57

标签: 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精灵的初始堆栈布局是什么?相当于http://asm.sourceforge.net/articles/startup.html会非常好。

更新2: 我遗漏了如何构建此代码。我是这样做的:

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

1 个答案:

答案 0 :(得分:1)

初始堆栈布局在堆栈指针处包含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