协慌网

登录 贡献 社区

LEA 指令的目的是什么?

对我来说,这就像一部时髦的 MOV。它的目的是什么?何时使用?

答案

正如其他人指出的那样,LEA(有效负载地址)通常被用作进行某些计算的 “技巧”,但这并不是其主要目的。 x86 指令集旨在支持 Pascal 和 C 等高级语言,在这些语言中,数组(尤其是 int 或小结构的数组)很常见。例如,考虑一个表示(x,y)坐标的结构:

struct Point
{
     int xcoord;
     int ycoord;
};

现在想象一下一条语句:

int y = points[i].ycoord;

其中points[] Point的数组。假设数组的基础已经在EBX ,并且变量iEAX ,并且xcoordycoord均为 32 位(因此ycoord在 struct 中的偏移量为 4 个字节),则可以将该语句编译为:

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

这将土地yEDX 。比例因子 8 是因为每个Point大小为 8 个字节。现在考虑与运算符&的 “地址” 一起使用的表达式:

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

在这种情况下,您不需要ycoord的值,但需要它的地址。这就是LEA (有效负载地址)的来源。编译器可以生成MOV

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

这将在ESI加载地址。

摘自 Abrash的 “汇编禅”:

LEA ,这是唯一执行内存寻址计算但实际上并未寻址内存的指令。 LEA接受标准的内存寻址操作数,但只不过将计算出的内存偏移量存储在指定的寄存器中即可,该寄存器可以是任何通用寄存器。

这给了我们什么? ADD不提供的两件事:

  1. 使用两个或三个操作数执行加法的能力,以及
  2. 将结果存储在任何寄存器中的能力;不只是源操作数之一。

LEA不会更改标志。

例子

  • LEA EAX, [ EAX + EBX + 1234567 ]计算EAX + EBX + 1234567 (这是三个操作数)
  • LEA EAX, [ EBX + ECX ]计算EBX + ECX而不会覆盖任何结果。
  • 如果您像 LEA EAX 那样使用常数,则乘以常数(乘以 2、3、5 或 9) LEA EAX, [ EBX + N * EBX ] (N 可以是 1,2,4,8)。

其他用例在循环中很方便: LEA EAX, [ EAX + 1 ]INC EAX之间的区别在于,后者改变了EFLAGS而前者却没有改变;这保留了CMP状态。

LEA指令的另一个重要特征是,它不会更改条件代码(例如CFZF ,而通过算术指令(例如ADDMUL计算地址。此功能降低了指令之间的依赖性,从而为编译器或硬件调度程序的进一步优化留出了空间。