1

呼び出し規約を使用する関数をcdecl作成しているため、関数を呼び出す前のレジスタの状態が保持されていることを確認する必要があります。

私の質問は、これが通常どのように実行されるかです。関数の開始時にスタック上のレジスタをプッシュし、関数の最後にそれらをレジスタにポップアウトするだけの問題ですか?

4

1 に答える 1

1

cdecl 呼び出し規則を使用する関数を作成しているため、関数を呼び出す前のレジスタの状態が保持されていることを確認する必要があります。

おそらくご存じのとおり、EAX、ECX、および EDX でやりたいことを自由に行うことができますが、それ以外のほとんどすべてを保存する必要があります。

私の質問は、これが通常どのように実行されるかです。関数の開始時にスタック上のレジスタをプッシュし、関数の最後にそれらをレジスタにポップアウトするだけの問題ですか?

はい、通常はこのように行われます。最初はすべてをプッシュし、戻る前にポップします。

ただし、代わりに呼び出し元保存レジスタを使用することが理にかなっている場合もあります。関数で EDX を使用したことがなく、その内容に触れる可能性のある方法で関数を呼び出していないとしましょう。しかし、関数で EDI を使用したいと考えています。EDI をスタックに保存することも、EDX に保存することもできます。

mov edx, edi
; Do something with EDI without corrupting EDX, e.g. string manipulation
mov edi, edx

それ以外の

push edi
; Do something with EDI, e.g. string manipulation
pop edi

レジスタを使用すると、スタックを使用するよりもわずかに高速になるため、たとえばこの関数をループで使用すると、目に見えるパフォーマンスの向上が得られる場合があります。

最初にすべてを保存し、戻る直前に復元する必要はないことに注意してください。使用する直前にレジスタを保存し、関数の途中で使い終わったらすぐに復元できます。

于 2015-01-08T13:49:38.110 に答える