什么是 LEA 指令?
在 x86 汇编语言中,LEA(Load Effective Address)指令用于**计算一个内存地址的值并存入寄存器**,但并不访问该地址对应的内存内容。
它非常适合用来做指针运算、地址偏移等操作。
基本语法
LEA destination, source
- destination:必须是一个寄存器(如
eax,ebx等) - source:是一个有效的内存地址表达式,如
[ebx + ecx*4 + 8]
实际示例
lea eax, [ebx + ecx*4 + 8]
假设:
ebx = 1000ecx = 3
那么上述指令的效果为:
eax = 1000 + 3 * 4 + 8 = 1020
注意:它**不会访问内存地址 1020 的内容**,只是把地址本身算出来放进 eax。
LEA 的常见用途
-
指针运算
mov esi, [ebp+8] ; 从栈中读取一个指针 lea eax, [esi+4] ; 相当于 pointer + 1(一个 int 是 4 字节) -
高效的乘法和加法
lea eax, [eax + eax*2] ; eax = eax * 3 -
数组索引
lea eax, [array + edi*4] ; 计算 array[edi] 的地址
LEA 与 MOV 的区别
| 指令 | 说明 |
|---|---|
mov eax, [ebx + 4] |
从内存地址 ebx + 4 中读取值到 eax |
lea eax, [ebx + 4] |
将地址 ebx + 4 的值计算后存入 eax |
C 编译器中生成的 LEA 示例
C 代码如下:
int foo(int* arr, int i) {
return arr[i + 2];
}
使用 GCC 编译并查看汇编输出(gcc -O2 -S foo.c -o foo.s)可能得到如下(简化后):
foo:
lea eax, [rsi+2]
mov eax, DWORD PTR [rdi+rax*4]
ret
解释:
rdi保存的是数组arr的首地址rsi是传入的索引ilea eax, [rsi + 2]把i + 2算好存入eax(不访问内存)- 接着通过
[rdi + rax*4]取数组中的第i + 2项(每项 4 字节)
64-bit 模式下 LEA 的用法
在 x86-64(即 64-bit 模式)中,LEA 同样强大,并能操作 64 位寄存器(如 rax, rbx, rsi, rdi 等)。
lea rax, [rbx + rcx*8 + 16]
这条指令的作用是:
rax = rbx + rcx * 8 + 16
常用于结构体成员访问、数组遍历、栈帧偏移等场景。
64-bit 示例:结构体成员地址计算
C 代码:
struct Point {
int x;
int y;
};
int* get_y(struct Point* p) {
return &p->y;
}
对应汇编(GCC 生成,优化后):
get_y:
lea rax, [rdi+4]
ret
这里假设 int 为 4 字节,y 紧随 x,所以 &p->y = p + 4。因此直接使用 lea 得到地址,而无需访问内存。
总结补充
LEA 是汇编语言中强大的工具之一。它不像名字那样“加载”数据,而是更像是一个“指针运算器”。
无论是做复杂偏移、模拟乘法、还是指针遍历,只要涉及地址计算,你都应该想到 LEA。
学习汇编语言,理解 LEA 是迈向系统底层编程的关键一步。
- 编译器很喜欢用
LEA来做常数加法、索引乘法,而不是使用加法或乘法指令 LEA在 64-bit 模式下可以处理更大的地址空间,更常见于系统级编程- 它提供了一种“零内存访问”的方式,极大提高了性能
汇编语言
英文:Understanding the LEA Instruction: A Powerful Tool for Address Calculation in x86 Assembly
本文一共 610 个汉字, 你数一下对不对.上一篇: 买借死 Buy Borrow Die: 富人如何合法避税而我们却在交税
下一篇: 用Copilot AI来审核区块链钱包代码
扫描二维码,分享本文到微信朋友圈
