2017-01-28 3 views
1

アセンブリ言語でLEAVE命令に関するいくつかの説明が必要スタック)。は、それは、これらの2つの命令の縮合物である、私はLEAVE機能明確に理解していなかった

POP EBPは、ESPが指す値を移動し、EBPに影響し、ESPを1ステップ下に移動します。

しかし、私は実際には、これら2つの操作が機能を残しているという事実にリンクしているのを見ていません(これは、LEAVEの目的です)。

どうすればいいですか?

+0

'LEAVE'の目的は、' ENTER'が行ったことを元に戻すこと、すなわち 'ENTER'によって作成されたスタックフレームを「フリー」にすることです。 – Michael

+0

だから、それは現在のスタックフレームを削除し、下のものを指していますか? – juRioqs75

+2

これは、ENTER命令の機能をバランスさせます。スタックフレームを設定して、再び破棄します。これらの命令が存在することを忘れてはなりません。プロセッサはまだ20年以上前にスーパースカラーではなかったのです。 –

答えて

2

共通プロローグ、ルーチンの開始時に命令のシーケンスは、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 

である - 同期して両方のバージョンを維持することを忘れやすいです。
ローカル変数の割り当て前にebpespの値であることを利用することができます。したがって、その値を復元することによって、それらをすべて効率的に解放します。

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 

は同等のプロローグです。


enterleaveコード空間を最適化するために使用することができるが乏しい命令です。

関連する問題