2012-04-04 69 views
2

我是新来的程序集,我刚刚熟悉了调用堆栈,所以对我一无所知。为了获得在Mac OS X中x86_64的命令行参数,我可以做到以下几点: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.然而,偶尔它是一些(看似)随机数。

编辑:另外,你能告诉我,如果我的堆栈绘图的其余部分是正确的?

回答

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 
+0

是啊,那更有意义。但是,为什么当我这样做: “** mov r10,[rsp + 32] **”然后 “** add r10,8 **” 然后将r10传递给printf,我得到段错误?这应该是argv [1],对吧? – 2012-04-04 05:53:44

+0

等等,我的**错误**。我认为argv实际上是“rsp + 40”,而不是32。我现在很困惑,但感谢您的帮助! – 2012-04-04 06:03:55

0

按照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将低于rbp一个eightbyte(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 <[email protected]>