の違いについて少し混乱しています
leal -4(%ebp), %eax
と
movl -4(%ebp), %eax
誰かが私にこれを説明できますか?
LEA (実効アドレスのロード) は、オペランドのアドレスを計算するだけで、実際に逆参照しません。ほとんどの場合、たとえば配列のインデックス付けなどの乗算と加算を組み合わせたような計算を行っているだけです。
この場合、単純な数値減算を行っています:の値をレジスタにleal -4(%ebp), %eax
代入するだけです。これは、宛先がソースの 1 つと同じである必要があることを除いて、単一の命令と同等です。%eax
%ebp - 4
sub
sub
対照的に、このmovl
命令は のメモリ位置にアクセスし、%ebp - 4
その値を に格納します%eax
。
これを別のプログラミング言語の観点から見たい場合は、次のようにします。
int var;
[ ... ]
func (var, &var);
次の (Linux x86_64) アセンブリ コードに評価されます。
[ ... ] 4: 8b 7c 24 0c mov 0xc(%rsp),%edi 8: 48 8d 74 24 0c lea 0xc(%rsp),%rsi d: e8 xx xx xx xx callq ... <機能> [ ... ]
%rdi
/%rsi
は 1番目/ 2番目の引数であるため、変数のアドレスlea ...
を取得し、同じ値をロード/ストアすることがわかります。 &var
mov ...
var
つまり、アセンブリでは、lea
代わりにの使用は、変数自体 (の値) ではなく、C/C++ でmov
のアドレス演算子の使用に似ています。&
lea
それよりもはるかに多くの用途がありますが、2つの違いについて明示的に尋ねました.
例として: mov
with メモリ オペランドは常にメモリ アクセス (ロードまたはストア) を実行しますが、メモリ オペランド tolea
は単にポインタ演算として扱われます。つまり、アドレスは計算および解決されますが、命令自体ではメモリ アクセスは発生しません。この二つ:
lea 1234(%eax, %ebx, 8), %ecx
movl (%ecx), ecx
結果は次のようになります。
movl 1234(%eax, %ebx, 8), %ecx
次の場合:
leal (%eax, %eax, 4), %eax
値%eax
を 5 で乗算します。
LEA
Intel 構文のロード実効アドレス (長い?) と同等です。
LEA と MOV はどちらも、たとえば変数へのオフセットをレジスタにロードできます。
MOV はメモリの内容をレジスタに転送することもできますが、LEA はできません。LEA と MOV の両方で、より効果的な計算を行うために使用できる「実効オフセット」を計算できます。