どのようにして、アセンブリ内で関数の引数を別の関数に転送するだけで、余分な数を追加することができますか?完璧な転送 - 組み立て
これまでのところ、私は2つの余分な引数を押して、もう1つの関数にjmpしました。それは有効ですか?私はそれを裸の関数にすると仮定すると、プロローグ/エピローグはありません。私はx86です。
どのようにして、アセンブリ内で関数の引数を別の関数に転送するだけで、余分な数を追加することができますか?完璧な転送 - 組み立て
これまでのところ、私は2つの余分な引数を押して、もう1つの関数にjmpしました。それは有効ですか?私はそれを裸の関数にすると仮定すると、プロローグ/エピローグはありません。私はx86です。
これを行うには、リターンアドレスをポップし、2つの引数を押して、スタックにリターンアドレスを戻してからジャンプさせる必要があります。
以下の説明では、私がティンカーのレジスタを予約していない環境で、純粋なスタックベースの呼び出し規約を使用していることを前提としています。予約されたレジスタがある場合(たとえば、Cプログラムによって呼び出されるASM関数を記述している場合など)、または呼び出し規約がレジスタベースである場合、状況は多少異なるはずです。
また、最後に必ず免責事項をお読みください。
方法のうちそれと...
あなたは、スタック上の2つのパラメータで呼ばれています機能を持っている想像してみてください。スタックフレームは、あなたの関数へのエントリで、次のようになります。
arg1
arg2
return addr
はの引数の順序(stdcall
対すなわちcdecl
)について屁理屈ないようにしましょう。
ここで、2つの引数と2つの引数を必要とする別の関数にコントロールを渡したいとします。
arg1
arg2
arg3
arg4
return addr
だからあなたの最初の関数は、戻りアドレスをポップ二つの新しいパラメータを追加し、リターンアドレスをプッシュして、ジャンプを行う必要があります:
その関数へのエントリでは、スタックフレームは次のようになります。passthrough:
; save the return address
pop ax
; Do stuff here to load values in BX and CX
; now push BX and CX (other parameters)
push bx
push cx
; restore the return address
push ax
; Branch to the new function.
; The new function's RETurn will return to the caller of this function
jmp new_function
(はい、私は16ビット命令であることやっただけなど、eax
にax
を変更します。)
また、これは非常に重要です:呼び出し先の場合のみ動作はスタックをクリーンアップする予定です。呼び出し側がスタックをクリーンアップすると予想される場合(通常はpop
またはスタックポインタを追加することによって)、呼び出し側は実際に4があるときに呼び出し元がスタックから2つのパラメータを削除することを期待しているため、この手法は失敗します。破損したスタックフレームになり、呼び出し元がret
命令を実行しようとすると、それは雑草に迷い込んでしまいます。
x86では、呼び出し元がクリーンアップする必要があります(呼び出し直後に 'add%esp'が表示されますが、巧妙なコンパイラではそれらをバッチすることもあります)。テールコールは、同じ数以下の引数でのみ行うことができます。 –
@Ben:x86にはどちらも必要ありません。言語および/またはオペレーティングシステム関数によって指定された呼び出し規約によって、どのメソッドが使用されるかが決まります。たとえば、Windowsの 'stdcall'は、Delphiと同様に、呼び出し先のクリーンアップを指定します。 'cdecl'呼び出し規約は呼び出し元のクリーンアップを指定します。呼び出し先のクリーンアップでは、 'ret 8'のような指示が表示されます。つまり、戻りアドレスがポップされた後に' esp'が8だけインクリメントされます。 –
他の機能のリターンアドレスはどうですか? –