の違いについて少し混乱しています
leal -4(%ebp), %eax
そして
movl -4(%ebp), %eax
誰かがこれを私に説明できますか?
[〜#〜] lea [〜#〜] (実効アドレスのロード)は、オペランドのaddressを計算するだけです。実際にはそれを逆参照しません。ほとんどの場合、それは、たとえば配列のインデックス付けのために、乗算と加算を組み合わせたような計算を行うだけです。
この場合、単純な数値減算を行っています。leal -4(%ebp), %eax
は、%eax
レジスタに%ebp - 4
の値を割り当てるだけです。これは単一のsub
命令と同等ですが、sub
は宛先をソースの1つと同じにする必要があることを除きます。
対照的に、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 ... <func> [...]
%rdi
/%rsi
は1st / 2nd 引数を見ると、lea ...
が変数のaddress&var
を取得するのに対し、mov ...
はvaluevar
をロード/保存していることがわかります同じ。
つまりアセンブリでは、lea
の代わりにmov
を使用することは、変数自体(の値)ではなく、C/C++で&
のアドレス演算子を使用することに似ています。
lea
はそれよりもはるかに多くの用途がありますが、2つの違いを明確に尋ねました。
説明:メモリオペランドを指定したmov
は常にメモリアクセス(ロードまたはストア)を実行しますが、lea
へのメモリオペランドはポインタ演算として扱われます。つまり、アドレスは計算され解決されますが、メモリアクセスはありません。命令自体で発生します。この二つ:
lea 1234(%eax, %ebx, 8), %ecx
movl (%ecx), ecx
結果は次と同じになります:
movl 1234(%eax, %ebx, 8), %ecx
一方、次のとおりです。
leal (%eax, %eax, 4), %eax
%eax
の値に5を掛けます。
Intel構文のLEA
に相当し、実効アドレスをロードします(長い?)。
LEAとMOVはどちらも、たとえば変数へのオフセットを含むレジスタをロードできます。
MOVはメモリ場所の内容をレジスタに転送することもできますが、LEAはできません。 LEAとMOVはどちらも「効果的なオフセット」を計算でき、計算をより効果的に行うために使用できます。