8

I just started tinkering with ASM and I'm not sure if my understanding of procedure calls is correct.

say at some point in the code there is a procedure call

call dword ptr[123]

and the procedure consists of only one command, ret:

ret 0004

what would be the effect of this procedure call, and where would the return value be stored? I read somewhere that a return value of 2 bytes would be stored in AX, but when I replace the procedure call by

mov AX, 0004

(together with the necessary NOPs) the program crashes.

4

4 に答える 4

12

x86 アセンブラーでは、ret命令へのパラメーターは次のことを意味します。

RET immediate

呼び出し元のプロシージャに戻り、スタックから即時バイトをポップします。

( Intel® 64 and IA-32 Architectures Software Developer's Manuals Vol 2Bからの引用)

したがって、次のように入力すると:

ret 0004

の直後に命令に戻りcall、スタックから 4 バイトをポップするように CPU に指示しています。呼び出しの前に 4 バイトをスタックにプッシュした場合、これは素晴らしいことです。

push eax
call dword ptr[123]

これは戻り値とは関係がないことに注意してください。実際、Assembly のプロシージャには、値が戻り値であることを指定する方法がありません。これはすべて慣習によって行われます。私が知っているほとんどのコンパイラはEAX戻り値を保持するために使用しますが、これは呼び出し元の関数がそこで結果を期待するためだけに当てはまります。

したがって、呼び出しコードは次のようになります。

call dword ptr [123]
mov dword ptr [result], eax

値 4 を返す関数は次のようになります。

mov eax, 4
ret
于 2009-08-09T10:33:35.273 に答える
2

それはすべて、使用されている呼び出し規約によって異なります。ここではウィキペディアの記事を繰り返すのではなく、定義を読んでください。

たとえば、C呼び出し規約では、戻り値はEAX / AX/ALになりますあなたの単一の命令にはそれがありません:それは何もしない約4バイトのパラメータ(おそらく単一のint)をとるvoid関数です。この呼び出し規約でスタックをクリーンアップするのは呼び出し先の義務であるため、それを無視して呼び出しを「movax」に置き換えることは機能しません。

また、16ビットドキュメントを読んでいるときに32ビットアセンブリをいじくり回しているのではないかと思います。大きな問題ではありませんが、違いに注意する必要があります。

于 2009-08-09T11:00:06.373 に答える
1
// possibly there are arguments pushed here
...
call dword ptr[123] // push next OP code offset in the stack and jump to procedure

// procedure
...
ret 0004 // pop offset, set EIP to that offset and decrease ESP by 4

プロシージャを呼び出す前にスタックに引数をプッシュした場合は、さらにESP を減らします。


プッシュされた引数がある場合、それらをポップしないため、プログラムがクラッシュします。現在のプロシージャの戻りオフセットは、プッシュされた引数の 1 つからオフセットとして値を取得するため、正しくありません。

于 2009-08-09T10:17:20.423 に答える
-1

I don't think the return value is stored in the register AX

于 2009-08-09T10:04:44.240 に答える