Assembly x86_64汇编命令行参数
要在Mac OS X上获取x86_64中的命令行参数,我可以执行以下操作:Assembly x86_64汇编命令行参数,assembly,stack,command-line-arguments,x86-64,Assembly,Stack,Command Line Arguments,X86 64,要在Mac OS X上获取x86_64中的命令行参数,我可以执行以下操作: _main: sub rsp, 8 ; 16 bit stack alignment mov rax, 0 mov rdi, format mov rsi, [rsp + 32] call _printf 其中格式为“%s”。rsi设置为argv[0] 因此,我从中得出了(我认为)堆栈最初的样子: top of stack <-
_main:
sub rsp, 8 ; 16 bit stack alignment
mov rax, 0
mov rdi, format
mov rsi, [rsp + 32]
call _printf
其中格式为“%s”。rsi设置为argv[0]
因此,我从中得出了(我认为)堆栈最初的样子:
top of stack
<- rsp after alignment
return address <- rsp at beginning (aligned rsp + 8)
[something] <- rsp + 16
argc <- rsp + 24
argv[0] <- rsp + 32
argv[1] <- rsp + 40
... ...
bottom of stack
栈顶
你离得很近
argv
是数组指针,而不是数组所在的位置。在C
中,它被写入char**argv
,因此您必须执行两个级别的解引用才能获得字符串
top of stack
<- rsp after alignment
return address <- rsp at beginning (aligned rsp + 8)
[something] <- rsp + 16
argc <- rsp + 24
argv <- rsp + 32
envp <- rsp + 40 (in most Unix-compatible systems, the environment
... ... string array, char **envp)
bottom of stack
...
somewhere else:
argv[0] <- argv+0: address of first parameter (program path or name)
argv[1] <- argv+8: address of second parameter (first command line argument)
argv[2] <- argv+16: address of third parameter (second command line argument)
...
argv[argc] <- argv+argc*8: NULL
栈顶
根据(3.2.3,参数传递),将main(int argc,char**argv)
的参数传递给(按从左到右的顺序)rdi
和rsi
,因为它们属于整数类envp
,如果使用它,将被传递到rdx
,以此类推。
gcc
将它们放入当前帧,如下所示(可能是为了方便?释放寄存器?):
当省略帧指针时,寻址相对于rsp
。通常,argv
将比rbp
低八个字节(argc
排在第一位,尽管这不是强制性的),因此:
# after prologue
mov rax, QWORD PTR [rbp-0x10] # or you could grab it from rsi, etc.
add rax, 0x8
mov rsi, QWORD PTR [rax]
mov edi, 0x40064c # format
call 400418 <printf@plt>
开场白之后
mov-rax,QWORD-PTR[rbp-0x10]#或者你可以从rsi等公司获得它。
添加rax,0x8
移动rsi,QWORD PTR[rax]
mov edi,0x40064c#格式
拨打400418
啊,是的,这更有意义。但是,为什么当我这样做:“mov r10,[rsp+32]”然后“添加r10,8”,然后将r10传递给printf时,我会得到一个segfault?那应该是argv[1],对吗?等等,我的错。我认为argv实际上是“rsp+40”,而不是32。大概我现在很困惑,但是谢谢你的帮助argc
和argv
不在堆栈上,x86-64系统V传递寄存器中第一个最多6个整数/指针arg。如果调用main
的东西在进程进入后没有对堆栈进行太多的调整(其中argv[]
数组本身在堆栈上,因此\u start
将执行类似于mov edi,[rsp]
(argc)和lea rsi,[rsp+8]
(argv)的操作,那么OP加载正好起作用获取main
的参数(以及另一个带有RDI*8的LEA以获取envp)。可能是为了方便?不,因为您在禁用优化的情况下编译,所以它会将所有内容溢出到内存中,调试器可以在其中读写它们。如果您在正常优化的情况下编译,gcc将像手动一样使用寄存器值。
# after prologue
mov rax, QWORD PTR [rbp-0x10] # or you could grab it from rsi, etc.
add rax, 0x8
mov rsi, QWORD PTR [rax]
mov edi, 0x40064c # format
call 400418 <printf@plt>