对我来说,这就像个古怪的MOV。它的目的是什么,我应该什么时候使用它?
发布于 2009-11-03 06:25:00
正如其他人指出的那样,LEA (load有效地址)经常被用作进行某些计算的“技巧”,但这并不是它的主要目的。x86指令集旨在支持Pascal和C等高级语言,其中数组--特别是ints或小型结构的数组--是常见的。例如,考虑表示(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"
这将使y
在EDX
登陆。8的比例因子是因为每个Point
的大小是8个字节。现在,考虑与“地址”操作符使用的相同表达式&:
int *p = &points[i].ycoord;
在这种情况下,您不需要ycoord
的值,而是它的地址。这就是加载有效地址(load effective )出现的地方。编译器可以生成MOV
,而不是
LEA ESI, [EBX + 8*EAX + 4]
它将在ESI
中加载地址。
发布于 2009-11-01 21:03:38
来自阿布拉什的“集会的禅宗”:
LEA
是执行内存寻址计算但实际上不寻址内存的唯一指令。LEA
接受标准内存寻址操作数,但只会将计算出的内存偏移量存储在指定的寄存器中,这可能是任何通用寄存器。
那能给我们什么?ADD
没有提供两件事:
LEA
不改变标志。
示例
LEA EAX, [ EAX + EBX + 1234567 ]
计算EAX + EBX + 1234567
(这是三个operands)LEA EAX, [ EBX + ECX ]
计算EBX + ECX
,而不用常量覆盖result.LEA EAX, [ EBX + N * EBX ]
一样使用它(N可以是1、2、4、8)。循环中的其他usecase很方便:LEA EAX, [ EAX + 1 ]
和INC EAX
的区别是后者改变了EFLAGS
,但是前者没有;这保留了CMP
状态。
发布于 2012-10-09 17:35:41
LEA
指令的另一个重要特性是它不改变条件代码(如CF
和ZF
),而使用算术指令(如ADD
或MUL
)计算地址。此特性降低了指令之间的依赖级别,从而为编译器或硬件调度程序进一步优化提供了空间。
https://stackoverflow.com/questions/1658294
复制相似问题