アセンブリ言語でLEAVE命令に関するいくつかの説明が必要スタック)。は、それは、これらの2つの命令の縮合物である、私はLEAVE機能明確に理解していなかった
POP EBP
は、ESPが指す値を移動し、EBPに影響し、ESPを1ステップ下に移動します。
しかし、私は実際には、これら2つの操作が機能を残しているという事実にリンクしているのを見ていません(これは、LEAVEの目的です)。
どうすればいいですか?
アセンブリ言語でLEAVE命令に関するいくつかの説明が必要スタック)。は、それは、これらの2つの命令の縮合物である、私はLEAVE機能明確に理解していなかった
POP EBP
は、ESPが指す値を移動し、EBPに影響し、ESPを1ステップ下に移動します。
しかし、私は実際には、これら2つの操作が機能を残しているという事実にリンクしているのを見ていません(これは、LEAVEの目的です)。
どうすればいいですか?
共通プロローグ、ルーチンの開始時に命令のシーケンスは、32ビットおよび16ビットの時代に
push ebp
mov ebp, esp
sub esp, <local_var_size>
push <clobbered_reg1>
push <clobbered_reg2>
...
何もここにカジュアルでなかった、命令の順序が重要であり、我々すべてのデータが容易とどれだけebp
(8以上の連続した正のオフセット、負のオフセットより低い又は等しい4としてローカルVARSのようなパラメータ)から、適切なポインタでアクセスする方法
|parN | <-- EBP + 04 + n*4 par1..parN = Routine parameters
... ... ra = Return address
|par2 | <-- EBP + 0ch o ebp = Original (caller) EBP
|par1 | <-- EBP + 08h lvar1..lavarM = Local variables
|ra | <-- EBP + 04h creg1..cregK = Clobbered registers
|o ebp| <-- EBP
|lvar1| <-- EBP - 04h
|lvar2| <-- EBP - 08h
... ...
|lvarM| <-- EBP - m*4
|creg1|
|creg2|
...
|cregK| <-- ESP
ルックで終わりますこのモデルはより大きい数のためにスケールするrのローカル変数またはパラメータ。
このため、ebp
はフレームポインタと呼ばれます。
エピローグはこれをすべて元に戻す必要があります。
一つの可能な変形は、しかし、これは<local_var_size>
を繰り返す必要
pop <clobbered_regK>
...
pop <clobbered_reg1>
add esp, <local_var_size>
pop ebp
ret n*4
である - 同期して両方のバージョンを維持することを忘れやすいです。
ローカル変数の割り当て前にebp
がesp
の値であることを利用することができます。したがって、その値を復元することによって、それらをすべて効率的に解放します。
pop <clobbered_regK>
...
pop <clobbered_reg1>
mov esp, ebp
pop ebp
ret n*4
しかし最後の3番目と2番目の命令は、leave
命令の機能です。したがって:
pop <clobbered_regK>
...
pop <clobbered_reg1>
leave
ret n*4
は同等のプロローグです。
enter
leave
コード空間を最適化するために使用することができるが乏しい命令です。
'LEAVE'の目的は、' ENTER'が行ったことを元に戻すこと、すなわち 'ENTER'によって作成されたスタックフレームを「フリー」にすることです。 – Michael
だから、それは現在のスタックフレームを削除し、下のものを指していますか? – juRioqs75
これは、ENTER命令の機能をバランスさせます。スタックフレームを設定して、再び破棄します。これらの命令が存在することを忘れてはなりません。プロセッサはまだ20年以上前にスーパースカラーではなかったのです。 –