2012-04-04 4 views
2

私はアセンブリが初めてで、コールスタックに慣れているので、私には裸でいます。 Mac OS Xのx86_64版でのコマンドライン引数を取得するために、私は次の操作を行うことができますx86_64アセンブリコマンドライン引数

形式は「%sの」ある
_main: 
    sub rsp, 8   ; 16 bit stack alignment 
    mov rax, 0 
    mov rdi, format 
    mov rsi, [rsp + 32] 
    call _printf 

。 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と書かれているため、文字列に到達するには2レベルの逆参照が必要です。

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

はいああ、それはより理にかなって:通常、argvしたがって、1 rbp以下eightbyte(それが義務付けられていないもののargcは、最初に来る)となります。しかし、なぜ私はそうするのですか? "** mov r10、[rsp + 32] **"そして "** add r10、8 **" そしてr10をprintfに渡すと、セグメンテーション? argv [1]でしょうか? –

+0

待って、私の**失敗**。私はargvが実際には "rsp + 40"、つまり32ではないと思う。たぶん。私は今はかなり混乱していますが、助けてくれてありがとう! –

0

それらはIntegerクラスのものであるので、AMD64 ABI(3.2.3、パラメータの受渡し)によれば、main(int argc, char **argv)のパラメータをrdi & rsi(左から右の順)に渡されます。 envpが使用されている場合は、rdxなどに渡されます。現在のフレームに gcc場所それらを(おそらく便宜上、レジスタを解放?)次のように

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

フレームポインタを省略した場合、アドレス指定はrspに対するものです。

# 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]>