对我来说,这就像一部时髦的电影。它的用途是什么?我应该什么时候使用它?
当前回答
LEA:只是一个“算术”指令。。
MOV在操作数之间传输数据,但lea只是在计算
其他回答
这里有一个例子。
// compute parity of permutation from lexicographic index
int parity (int p)
{
assert (p >= 0);
int r = p, k = 1, d = 2;
while (p >= k) {
p /= d;
d += (k << 2) + 6; // only one lea instruction
k += 2;
r ^= p;
}
return r & 1;
}
使用-O(optimize)作为编译器选项,gcc将找到指定代码行的lea指令。
LEA指令可用于避免CPU对有效地址进行耗时的计算。如果地址被重复使用,则将其存储在寄存器中而不是每次使用时计算有效地址更有效。
LEA指令的另一个重要特征是它不会改变条件代码(如CF和ZF),而通过ADD或MUL等算术指令计算地址则会改变。这一特性降低了指令之间的依赖程度,从而为编译器或硬件调度器的进一步优化腾出了空间。
所有正常的“计算”指令,如加法、异或设置状态标志,如零、符号。如果使用复杂的地址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(负载有效地址)经常被用作进行某些计算的“技巧”,但这并不是它的主要目的。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"
其将在EDX中降落y。比例因子为8是因为每个点的大小为8字节。现在考虑与“address of”运算符使用的相同表达式&:
int *p = &points[i].ycoord;
在这种情况下,您不需要ycoord的值,而是需要它的地址。这就是LEA(加载有效地址)的作用
LEA ESI, [EBX + 8*EAX + 4]
这将在ESI中加载地址。
推荐文章
- Trap和中断的区别是什么?
- 为什么程序不是经常用汇编编写的?
- 保护可执行文件不受逆向工程的影响?
- “每个程序员应该知道的关于内存的事情”有多少仍然是有效的?
- 在GDB中显示当前的组装指令
- 为什么引入无用的MOV指令会加速x86_64汇编中的紧循环?
- ARM架构与x86有何不同?
- 为什么GCC在实现整数除法时使用奇数乘法?
- 基指针和堆栈指针到底是什么?他们指的是什么?
- 汇编代码vs机器代码vs目标代码?
- 什么是回跳线?它是如何工作的?
- 提交到App Store的问题:不支持架构x86
- “switch”比“if”快吗?
- 为什么Java在连续整数上的切换与添加的情况下运行得更快?
- 多核汇编语言是什么样子的?