1. ホーム
  2. c

[解決済み】ベースポインタとスタックポインタとは一体何でしょうか?これらは何を指しているのでしょうか?

2022-04-16 04:08:37

質問

使用方法 この例 この例では、DrawSquare() が DrawLine() を呼び出しています。

(この図では、ハイアドレスが下、ローアドレスが上になっていることに注意してください)

を説明できる人はいますか? ebpesp は、この文脈の中にあるのでしょうか?

見たところ、スタックポインタは常にスタックの先頭を指し、ベースポインタは現在の関数の先頭を指すということでしょうか。それとも何ですか?


edit: ウィンドウズ・プログラムの文脈での意味です。

edit2: また、どのように eip も動作するのですか?

edit3です。 MSVC++の以下のようなコードがあります。

var_C= dword ptr -0Ch
var_8= dword ptr -8
var_4= dword ptr -4
hInstance= dword ptr  8
hPrevInstance= dword ptr  0Ch
lpCmdLine= dword ptr  10h
nShowCmd= dword ptr  14h

これらはすべてdwordsであり、したがってそれぞれ4バイトを要するようです。ですから、hInstanceからvar_4まで4バイトのギャップがあることがわかります。これは何でしょうか?wikipediaの画像にあるように、リターンアドレスだと思うのですが?


(編集部注:マイケルさんの回答から、質問にふさわしくない長文の引用を削除しましたが、フォローの質問が編集されています)。

というのも、関数呼び出しの流れは

* Push parameters (hInstance, etc.)
* Call function, which pushes return address
* Push ebp
* Allocate space for locals

私の質問(最後の質問です!)は、私が呼び出したい関数の引数をポップした瞬間から、Prologが終了するまで、一体何が起こっているのでしょうか?私はその間にebp, espがどのように変化するかを知りたいのです(私はすでにプロローグがどのように動作するかを理解しています、私はただ、スタックに引数をプッシュした後、プロローグの前に何が起こっているかを知りたいのです)。

どのように解決するのですか?

esp はおっしゃるとおり、スタックの一番上です。

ebp は通常 esp を関数の先頭で使用します。関数のパラメータとローカル変数にアクセスするには、それぞれ、定数オフセットを ebp . すべての x86 呼び出し規約では ebp は、関数呼び出しの間、保存されます。 ebp は実際には前のフレームのベースポインタを指すので、デバッガでスタックウォークしたり、他のフレームのローカル変数を見たりすることが可能になります。

ほとんどの関数プロローグは次のようなものです。

push ebp      ; Preserve current frame pointer
mov ebp, esp  ; Create new frame pointer pointing to current stack top
sub esp, 20   ; allocate 20 bytes worth of locals on stack.

そして、この関数の後半で、次のようなコードを書くことができます(両方のローカル変数が4バイトであると仮定します)。

mov [ebp-4], eax    ; Store eax in first local
mov ebx, [ebp - 8]  ; Load ebx from second local

FPOまたは フレームポインターオミット を有効にすることで、実際にこれを排除して ebp を別のレジスタとして使用し、ローカルに直接アクセスすることができます。 esp しかし、この場合、デバッガは以前の関数呼び出しのスタックフレームに直接アクセスできなくなるため、デバッグが少し難しくなります。

EDIT

更新された質問に対して、スタックに欠けている2つのエントリは、次のとおりです。

var_C = dword ptr -0Ch
var_8 = dword ptr -8
var_4 = dword ptr -4
*savedFramePointer = dword ptr 0*
*return address = dword ptr 4*
hInstance = dword ptr  8h
PrevInstance = dword ptr  0C
hlpCmdLine = dword ptr  10h
nShowCmd = dword ptr  14h

これは、関数呼び出しの流れが

  • パラメータをプッシュする ( hInstance など)
  • 関数を呼び出し、戻り値のアドレスをプッシュする
  • プッシュ ebp
  • ローカル用スペースの確保