現在のスタックフレームポインタと以前のスタックフレームポインタ(つまりbpレジスタ)を抽出し、標準のスタックフレーム構造を使用して、現在のルーチンへの呼び出しで渡されました。どちらの単位がchar、shortまたはlongであるか、それらの2つがlong long/__ int64パラメーターである可能性があるかどうかを判断することはできません。
私はこれについてもう少し考えました。典型的な関数呼び出し "func(a、b)"を考えてみましょう。あなたは(x86-64のために推奨されるいくつかのx86-32コンパイラオプションおよびインテル)レジスタ内のパラメータを持っていない限り、呼び出すコードは、コードが次にあなたがFUNCの処理に来るこの
; long *esp,*ebp;
push b ; *(--esp)=b;
push a ; *(--esp)=a;
call func ; *(--esp)=return_address_location;
return_address_location:
add esp,8 ; esp+=2; // free memory allocated for passing parameters
のように判明するでしょう
func:
push ebp ; *(--esp)=(long) ebp; // save current ebp <=> current stack frame
mov ebp,esp ; ebp=esp; // create new stack frame in ebp
sub esp,16 ; esp-=4; // reserve space for local variables <=> sizeof(long)*4
(func code ...)
funcに入っていて、パラメータにアクセスする必要があるときは、ebp + 2とebp + 3でアドレス指定します(* ebpには前のebp、ebp + 1に戻りアドレスが入ります)。ローカル変数にアクセスする必要があるときは、ebp-4からebp-1でそれらを扱います(すべてロングではない場合、いくつかのパッキングオプションが設定されていると過度に単純化されるかもしれません)。
中のfuncがその事を行っている、あなたが返す必要があります後:
mov esp,ebp ; esp=ebp; // unreserve space for local variables
pop ebp ; ebp=*(esp++); // restore previous ebp <=> previous stack frame
ret ; eip=*(esp++); // pop return address into instruction pointer
あなたも(パラメータを渡すための)最初のスタック割り当てが右戻った後に解放される方法について説明します最初のスニペットから。
いくつかのヒント:
- は、コール/リターン シーケンスを シングルステップ( 命令による指示)しながら、自分のために数学を行うと、あなたは、元のを解決する方法 のアイデアを得るでしょう問題。この ので それが
- がローカルバッファに誤って計算 のmemset/memcpyのを想像して にそれを破壊する方法を知って良いことだすべての のアーキテクチャや実装上 多かれ少なかれ同じに見える基本的なスタックの処理でありますリターンアドレスを含む スタック上のデータ、 前のスタックフレームなど
- テイクDSの値をメモして、SS (データおよびスタックのセレクタ)と 場合、彼らはあなたの ソリューションのmemcpyを使用することができます正確に同じ値が含まれています〜 コピーあなたが&を使用することができ、DS = ssはFUNC内部 から渡されたパラメータの アドレスを見つけるために、場合それが
- を助けた場合どんな データ検査のためのメモリや (& PARAM1、& PARAM2)
にスタックからのパラメーター
- (彼ら がマルチスレッド アプリケーションであるかもしれないと)同等のds及びssのかは、あなたは、DSとSSが異なる 状況を処理します「これまで 取り組む」使用 memcpyのバリアントが必要になります場合は
ポインタを関数に渡すことについて質問していますか?関数内から引数へのポインタを取得していますか? –
*名前付き*パラメータ、または*実際の*パラメータを "varargs"関数に渡しているのですか? – Pointy
私は存在しないのですか?しかし、なぜそれが必要ですか?あなたはまだ関数にタブポインタを与えることができます(私は質問を理解するためにsurではありません)。 –