787

私にとっては、ファンキーな MOV のように思えます。その目的は何ですか?いつ使用する必要がありますか?

4

17 に答える 17

918

他の人が指摘しているように、LEA (ロード有効アドレス) は特定の計算を行うための「トリック」としてよく使用されますが、それが主な目的ではありません。x86 命令セットは、Pascal や C などの高水準言語をサポートするように設計されており、配列 (特に int の配列または小さな構造体) が一般的です。たとえば、(x, y) 座標を表す構造体を考えてみましょう。

struct Point
{
     int xcoord;
     int ycoord;
};

次のようなステートメントを想像してみてください。

int y = points[i].ycoord;

points[]配列ですPoint。配列のベースが既に にEBXあり、変数iが にEAXあり、xcoordおよびycoordがそれぞれ 32 ビット (ycoord構造体のオフセット 4 バイト) であると仮定すると、このステートメントは次のようにコンパイルできます。

MOV EDX, [EBX + 8*EAX + 4]    ; right side is "effective address"

に着陸yEDXます。スケール係数が 8 であるのは、それぞれPointのサイズが 8 バイトであるためです。ここで、"address of" 演算子 & で使用される同じ式を考えてみましょう。

int *p = &points[i].ycoord;

この場合、 の値でycoordはなく、そのアドレスが必要です。ここでLEA(load effective address) の出番です。 の代わりにMOV、コンパイラは生成できます

LEA ESI, [EBX + 8*EAX + 4]

にアドレスをロードしますESI

于 2009-11-03T06:25:00.017 に答える
610

Abrash著「組み立ての禅」より:

LEA、メモリ アドレス計算を実行するが、実際にはメモリをアドレス指定しない唯一の命令です。LEA標準のメモリ アドレッシング オペランドを受け入れますが、計算されたメモリ オフセットを指定されたレジスタ (任意の汎用レジスタ) に格納するだけです。

それは私たちに何を与えますか?ADD提供しない2 つのこと:

  1. 2 つまたは 3 つのオペランドで加算を実行する機能、および
  2. 結果を任意のレジスタに格納する機能。ソースオペランドの 1 つだけではありません。

フラグLEAを変更しません。

  • LEA EAX, [ EAX + EBX + 1234567 ]計算EAX + EBX + 1234567します (3 つのオペランドです)
  • LEA EAX, [ EBX + ECX ]EBX + ECXどちらも結果でオーバーライドせずに計算します。
  • 定数による乗算 (2、3、5、または 9)、次のように使用する場合LEA EAX, [ EBX + N * EBX ](N は 1、2、4、8)

LEA EAX, [ EAX + 1 ]他のユースケースはループで便利です。との違いINC EAXは、後者は変更されますEFLAGSが、前者は変更されないことです。これによりCMP状態が保持されます。

于 2009-11-01T21:03:38.647 に答える
126

この命令のもう 1 つの重要な特徴は、またはのような算術命令によってアドレスを計算するときに、やLEAなどの条件コードを変更しないことです。この機能により、命令間の依存関係のレベルが低下するため、コンパイラまたはハードウェア スケジューラによるさらなる最適化の余地が生まれます。CFZFADDMUL

于 2012-10-09T17:35:41.383 に答える
108

すべての説明にもかかわらず、LEA は算術演算です。

LEA Rt, [Rs1+a*Rs2+b] =>  Rt = Rs1 + a*Rs2 + b

その名前は、シフト+追加操作には非常に愚かです。その理由は、上位の回答ですでに説明されています (つまり、高レベルのメモリ参照を直接マップするように設計されています)。

于 2011-08-15T21:43:29.480 に答える
88

たぶん、LEA命令に関する別のことです。レジスタを 3、5、または 9 で高速に乗算するために LEA を使用することもできます。

LEA EAX, [EAX * 2 + EAX]   ;EAX = EAX * 3
LEA EAX, [EAX * 4 + EAX]   ;EAX = EAX * 5
LEA EAX, [EAX * 8 + EAX]   ;EAX = EAX * 9
于 2009-11-02T10:16:28.683 に答える
70

lea「ロード実効アドレス」の略です。ソースオペランドによる位置参照のアドレスをデスティネーションオペランドにロードします。たとえば、次の目的で使用できます。

lea ebx, [ebx+eax*8]

1 つの命令で (64 ビット/要素の配列で)ebxポインター項目をさらに移動します。eax基本的に、x86 アーキテクチャでサポートされている複雑なアドレッシング モードを利用して、ポインターを効率的に操作できます。

于 2009-11-01T21:00:24.813 に答える
30

The biggest reason that you use LEA over a MOV is if you need to perform arithmetic on the registers that you are using to calculate the address. Effectively, you can perform what amounts to pointer arithmetic on several of the registers in combination effectively for "free."

What's really confusing about it is that you typically write an LEA just like a MOV but you aren't actually dereferencing the memory. In other words:

MOV EAX, [ESP+4]

This will move the content of what ESP+4 points to into EAX.

LEA EAX, [EBX*8]

This will move the effective address EBX * 8 into EAX, not what is found in that location. As you can see, also, it is possible to multiply by factors of two (scaling) while a MOV is limited to adding/subtracting.

于 2015-05-05T22:22:04.190 に答える
26

8086 には、レジスタ オペランドと実効アドレスを受け取り、その実効アドレスのオフセット部分を計算するための計算を実行し、計算されたアドレスによって参照されるレジスタとメモリを含むいくつかの操作を実行する命令の大規模なファミリがあります。実際のメモリ操作をスキップすることを除いて、そのファミリの命令の 1 つを上記のように動作させるのはかなり簡単でした。したがって、指示:

mov ax,[bx+si+5]
lea ax,[bx+si+5]

内部的にはほぼ同じように実装されていました。違いはスキップされたステップです。どちらの命令も次のように機能します。

temp = fetched immediate operand (5)
temp += bx
temp += si
address_out = temp  (skipped for LEA)
trigger 16-bit read  (skipped for LEA)
temp = data_in  (skipped for LEA)
ax = temp

インテルがこの命令を含める価値があると考えた理由については、正確にはわかりませんが、実装が安価であるという事実が大きな要因だったでしょう。BPもう 1 つの要因は、Intel のアセンブラがシンボルをレジスタに対して相対的に定義できるという事実でした。が-relative シンボル (例: )fnordとして定義されている場合、次のように言うことができます。BPBP+8

mov ax,fnord  ; Equivalent to "mov ax,[BP+8]"

stoswBP相対アドレスにデータを保存するようなものを使用したい場合は、次のように言うことができます

mov ax,0 ; Data to store
mov cx,16 ; Number of words
lea di,fnord
rep movs fnord  ; Address is ignored EXCEPT to note that it's an SS-relative word ptr

より便利でした:

mov ax,0 ; Data to store
mov cx,16 ; Number of words
mov di,bp
add di,offset fnord (i.e. 8)
rep movs fnord  ; Address is ignored EXCEPT to note that it's an SS-relative word ptr

ワールドの「オフセット」を忘れると[BP+8]、値 8 ではなく、 location の内容が に追加されることに注意してくださいDI。おっとっと。

于 2012-04-29T19:46:51.630 に答える
9

LEA 命令を使用すると、CPU による実効アドレスの時間のかかる計算を回避できます。アドレスを繰り返し使用する場合は、使用するたびに実効アドレスを計算するよりも、レジスタに格納する方が効率的です。

于 2013-06-04T20:32:59.460 に答える
5

LEA : 単なる「算術」命令..

MOV はオペランド間でデータを転送しますが、lea は計算す​​るだけです

于 2015-05-05T21:06:00.380 に答える