Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/56.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
调用glibc时x86-64 ELF初始堆栈布局_C_Assembly_X86 64_Nasm_Glibc - Fatal编程技术网

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

调用glibc时x86-64 ELF初始堆栈布局,c,assembly,x86-64,nasm,glibc,C,Assembly,X86 64,Nasm,Glibc,基本上,我通读了部分,在第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,

基本上,我通读了部分,在第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的初始堆栈布局是什么吗?一份相当于一份工作的报告会非常好

更新2: 我遗漏了如何构建这段代码。我通过以下方式做到这一点:

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

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

pop %rdi
mov %rsp,%rsi
call main
pop %rdi
pop %rdi
call puts
xor %edi,%edi
jmp exit
实际上,通常有一个包装函数调用
main
,而不是启动代码直接调用它

如果只想打印
argv[0]
,可以执行以下操作:

pop %rdi
mov %rsp,%rsi
call main
pop %rdi
pop %rdi
call puts
xor %edi,%edi
jmp exit

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

pop %rdi
mov %rsp,%rsi
call main
pop %rdi
pop %rdi
call puts
xor %edi,%edi
jmp exit
实际上,通常有一个包装函数调用
main
,而不是启动代码直接调用它

如果只想打印
argv[0]
,可以执行以下操作:

pop %rdi
mov %rsp,%rsi
call main
pop %rdi
pop %rdi
call puts
xor %edi,%edi
jmp exit

嗨,谢谢你的回复。只是澄清一下,我不是用一个main函数调用一个C程序,而是使用C库函数。我更新了问题中代码的构建方式。我尝试让另一个全局标签调用主标签,但在链接阶段失败(gcc用于链接代码)。显然,在这种情况下,main必须是一个全局标签。如果要使用libc函数,应该注意绕过libc启动代码可能会导致它们崩溃。例如,glibc可能想要初始化
%gs
线程本地存储选择器,即使没有使用线程,也要使用它进行
syscenter
类型的系统调用,并在那里存储其他随机垃圾。您应该在asm中创建一个全局
main
,并让libc启动代码调用它,或者完全忽略libc并在asm中执行所有系统调用。您好,我在这里绕过libc启动代码了吗?我一直在关注Jeff Duntemann的“逐步汇编语言”如何从nasm调用C代码。如果我这样做的话,你能给我举个例子说明如何不绕过libc启动代码吗?谢谢哦,我是个傻瓜。不知怎的,我以为你写了一个
\u start
入口点,因为大多数人都是这样做的。如果使用了
main
,那么堆栈将不包含任何有意义的内容,并且
rdi
中的参数将是
argc
,而
rsi
中的参数将是
argv
(类型为
char**
\u start
get
argc
后跟堆栈上的字符串指针数组,而
main
get
argc
后跟
argv
(指向字符串指针数组的指针),后跟指向环境变量字符串指针数组的指针(通常未使用且非标准)。您好,谢谢你的回复。只是澄清一下,我不是用一个main函数调用一个C程序,而是使用C库函数。我更新了问题中代码的构建方式。我尝试让另一个全局标签调用主标签,但在链接阶段失败(gcc用于链接代码)。显然,在这种情况下,main必须是一个全局标签。如果要使用libc函数,应该注意绕过libc启动代码可能会导致它们崩溃。例如,glibc可能想要初始化
%gs
线程本地存储选择器,即使没有使用线程,也要使用它进行
syscenter
类型的系统调用,并在那里存储其他随机垃圾。您应该在asm中创建一个全局
main
,并让libc启动代码调用它,或者完全忽略libc并在asm中执行所有系统调用。您好,我在这里绕过libc启动代码了吗?我一直在关注Jeff Duntemann的“逐步汇编语言”如何从nasm调用C代码。如果我这样做的话,你能给我举个例子说明如何不绕过libc启动代码吗?谢谢哦,我是个傻瓜。不知怎的,我以为你写了一个
\u start
入口点,因为大多数人都是这样做的。如果使用了
main
,那么堆栈将不包含任何有意义的内容,并且
rdi
中的参数将是
argc
,而
rsi
中的参数将是
argv
(类型为
char**
\u start
获取堆栈上的
argc
后接字符串指针数组,而
main
获取
argc
,后接
argv
(字符串指针数组),后接指向环境变量字符串指针数组的指针(通常未使用且非标准)。