对我来说,这就像一部时髦的电影。它的用途是什么?我应该什么时候使用它?
当前回答
LEA vs MOV(回复原始问题)
LEA不是一个时髦的MOV。当您使用MOV时,它会计算地址并访问内存。LEA只计算地址,实际上不访问内存。这就是区别。
在8086及更高版本中,LEA仅将最多两个源寄存器和一个立即数的和设置为目标寄存器。例如,lea-bp,[bx+si+3]将bx加si加3的和设置到bp寄存器。无法实现此计算以将结果保存到带有MOV的寄存器中。
80386处理器引入了一系列缩放模式,其中索引寄存器值可以乘以有效的缩放因子以获得位移。有效比例因子为1、2、4和8。因此,您可以使用lea-ebp、[ebx+esi*8+3]等指令。
LDS和LES(可选进一步阅读)
与LEA相反,有指令LDS和LES,相反,它们将值从内存加载到一对寄存器:一个段寄存器(DS或ES)和一个通用寄存器。其他寄存器也有版本:分别用于FS、GS和SS段寄存器的LFS、LGS和LSS(80386中介绍)。
因此,这些指令加载“远”指针-一个由16位段选择器和16位(或32位,取决于模式)偏移量组成的指针,因此在16位模式下,远指针的总大小为32位,在32位模式下为48位。
这些是16位模式的方便说明,无论是16位实际模式还是16位保护模式。
在32位模式下,由于操作系统将所有段基设置为零(平面内存模型),所以不需要加载这些指令,因此不需要加载段寄存器。我们只使用32位指针,而不是48位指针。
在64位模式下,不执行这些指令。它们的操作码会导致访问违规中断(异常)。自从Intel实施VEX“矢量扩展”(AVX)以来,Intel采用了LDS和LES的操作码,并开始将它们用于VEX前缀。正如Peter Cordes所指出的,这就是为什么在32位模式下只能访问x/ymm0..7的原因(引用):“VEX前缀经过精心设计,仅与32位模式中LDS和LES的无效编码重叠,其中RÜxÜBÜ均为1。这就是为什么某些位在VEX前缀中被反转的原因”。
其他回答
也许只是LEA指令的另一件事。您还可以使用LEA将寄存器快速乘以3、5或9。
LEA EAX, [EAX * 2 + EAX] ;EAX = EAX * 3
LEA EAX, [EAX * 4 + EAX] ;EAX = EAX * 5
LEA EAX, [EAX * 8 + EAX] ;EAX = EAX * 9
来自Abrash的“装配禅”:
LEA,唯一执行内存寻址计算但实际上不寻址内存的指令。LEA接受标准内存寻址操作数,但只会将计算出的内存偏移量存储在指定寄存器中,该寄存器可以是任何通用寄存器。这给了我们什么?ADD没有提供的两件事:使用两个或三个操作数执行加法的能力,以及将结果存储在任何寄存器中的能力;而不仅仅是源操作数之一。
执法机关不改变旗帜。
示例
LEA EAX,[EAX+EBX+1234567]计算EAX+EBX+134567(即三个操作数)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状态。
LEA指令可用于避免CPU对有效地址进行耗时的计算。如果地址被重复使用,则将其存储在寄存器中而不是每次使用时计算有效地址更有效。
所有正常的“计算”指令,如加法、异或设置状态标志,如零、符号。如果使用复杂的地址AX-xor:=mem[0x33+BX+8*CX],则标志将根据xor操作设置。
现在您可能需要多次使用该地址。将这样的地址加载到寄存器中并不是为了设置状态标志,幸运的是,它并没有。短语“加载有效地址”使程序员意识到这一点。这就是奇怪表情的由来。
很明显,一旦处理器能够使用复杂的地址来处理其内容,它就能够将其计算用于其他目的。实际上,它可以用于在一条指令中执行转换x<-3*x+1。这是汇编程序设计中的一条一般规则:无论它如何摇晃你的船,都要使用指令。唯一重要的是指令所体现的特定转换是否对您有用。
要旨
MOV, X| T| AX'| R| BX|
and
LEA, AX'| [BX]
对AX具有相同的影响,但对状态标志没有影响。(这是ciasdis符号。)
LEA指令的另一个重要特征是它不会改变条件代码(如CF和ZF),而通过ADD或MUL等算术指令计算地址则会改变。这一特性降低了指令之间的依赖程度,从而为编译器或硬件调度器的进一步优化腾出了空间。
推荐文章
- 测试点%eax %eax
- Trap和中断的区别是什么?
- 为什么程序不是经常用汇编编写的?
- 保护可执行文件不受逆向工程的影响?
- “每个程序员应该知道的关于内存的事情”有多少仍然是有效的?
- 在GDB中显示当前的组装指令
- 为什么引入无用的MOV指令会加速x86_64汇编中的紧循环?
- ARM架构与x86有何不同?
- 为什么GCC在实现整数除法时使用奇数乘法?
- 基指针和堆栈指针到底是什么?他们指的是什么?
- 汇编代码vs机器代码vs目标代码?
- 什么是回跳线?它是如何工作的?
- 提交到App Store的问题:不支持架构x86
- “switch”比“if”快吗?
- 为什么Java在连续整数上的切换与添加的情况下运行得更快?