x86_64汇编命令行参数

时间:2012-04-04 03:14:01

标签: 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
               <- 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.但是,偶尔会有一些(看似)随机数。

另外,你能告诉我堆叠图的其余部分是否正确吗?

2 个答案:

答案 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