2016-11-03 5 views
1

はじめに、私は、機能的なアセンブリプログラマであることを知るために必要なことの大部分を理解するために、アセンブリの十分な背景を持っていると言いたいと思います。残念ながら、Windows API呼び出しが戻りアドレスの観点からどのように機能するかはわかりません。ここで スタックはWindows関数呼び出しでどのように設定されますか?

は、使用してWindows用のガスアセンブリで書かれたいくつかのサンプルコードですMinGWの者として、このコードはコンパイルされ、組み立て後に実行

.extern [email protected] 
    .text 
    .globl _main 
_main: 
    pushl $0 
    call [email protected] 

アセンブラ、リンカなどのMinGWのLD ... ...など

as program.s -o program.o 
私の理解、WindowsのAPIから

そして、それを結ぶ...

ld program.o -o program.exe -lkernel32 

上記のように、呼び出しはプッシュ命令を介して引数を受け取ります。その後、通話中。

call [email protected] 

関数の戻りアドレスがスタックに配置されます。そして、これが私が混乱しているところです。この関数は、すべての引数をスタックからポップします。

私は、スタックが最初に出てくるので、スタックの引数をポップしているときに、最初にリターンアドレスをポップするので、私は混乱しています。議論が最初に来て、リターンアドレスが次に来たので、それは技術的に最初に破棄されるだろう。

私の質問は、プッシュ操作を介して引数をスタックに配置された関数呼び出しと戻りアドレスに渡した後、スタックのレイアウトがどのように見えるかです。引数と戻りアドレスは、実行される関数によってどのようにスタックからポップされますか?最後に、戻りアドレスがスタックからポップされ、関数呼び出しは戻りアドレスで指定されたアドレスに戻りますか?

+0

良い例では、ExitProcess()はまったく返されません。 –

+0

値を返しませんが、スタック上にリターンアドレスがあります。 ret命令(最後にチェックした\ xc3)で復帰すると、スタックの戻り値がポップされ、実行フローがWindows APIに送られてから、関数呼び出しを開始した呼び出し命令の次の命令最初の場所。 – August

+0

Turbo J氏によると、ExitProcessは返されません。スタックにリターンアドレスがありますが、決して使用されず、関数はRET命令を実行しません。関数の名前によれば、関数はプロセスを終了させます。つまり、呼び出し元が存在しなくなるため、呼び出し元に戻ることはできません。 –

答えて

6

ほとんどすべてのWindows API関数はstdcall calling conventionを使用します。これは通常の "cdecl"のような働きをしますが、呼び出された関数が引数を取り除く責任を負っていることを除いては、これは正常に動作します。これは、オプションの即値オペランドをとるRET命令を使用して行います。このオペランドは、最初に戻り値をポップした後にスタックをポップアウトするバイト数です。

cdeclとstdcallの両方の呼び出し規約では、関数の実行中に関数の引数がスタックからポップされません。それらはスタックに残され、ESPまたはEBP相対アドレス指定を使用してアクセスされます。したがって、ExitProcessがその引数にアクセスする必要があるときは、mov 4(%esp), %eaxまたはmov 4(%ebp), %eaxのような命令を使用します。

+0

いいえ、戻り値のアドレスの前に関数の引数がスタックにプッシュされていない場合、戻り値のアドレスを最初にポップすることなく関数が引数をどのようにポップすることができますか? – August

+4

@August引数が返されるまで引数をポップアウトしません。 –

+0

ああ、それはリターンアドレスをポップし、その後、それが返される前に引数をポップしますか? – August

関連する問題