要在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
<- 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
等等。对不起,如果这很难读。我想知道什么是[某事]。经过几次测试后,我发现它通常只有0.但是,偶尔会有一些(看似)随机数。
另外,你能告诉我堆叠图的其余部分是否正确吗?
答案 0 :(得分:1)
根据AMD64 ABI(3.2.3,参数传递),main(int argc, char **argv)
的参数传递给(按从左到右的顺序)rdi
&amp; rsi
因为它们属于INTEGER类。 envp
,如果使用的话,会被传递到rdx
,依此类推。
gcc
将它们放入当前帧中(假设是为了方便起见?释放寄存器?):
mov DWORD PTR [rbp-0x4], edi
mov QWORD PTR [rbp-0x10], rsi
当省略帧指针时,寻址相对于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>
答案 1 :(得分:0)
你把它关闭了。
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