3

要在 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。然而,偶尔,它是一些(看似)随机数。

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

4

2 回答 2

2

根据AMD64 ABI(3.2.3,参数传递),参数main(int argc, char **argv)被传递给(按从左到右的顺序)rdi&,rsi因为它们属于 INTEGER 类。envp, 如果它被使用, 将被传递到rdx, 等等。 gcc按如下方式将它们放入当前帧(大概是为了方便?释放寄存器?):

mov    DWORD PTR [rbp-0x4],  edi
mov    QWORD PTR [rbp-0x10], rsi

当省略帧指针时,寻址是相对于rsp. 通常,argv将是一个八字节以下rbpargc首先出现,尽管这不是强制性的),因此:

# 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>
于 2012-04-04T07:47:08.407 回答
1

你有它关闭。

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
于 2012-04-04T05:26:26.300 回答