深入浅出 LEA 指令: x86 汇编中的地址计算神器
什么是 LEA 指令?
在 x86 汇编语言中,LEA
(Load Effective Address)指令用于**计算一个内存地址的值并存入寄存器**,但并不访问该地址对应的内存内容。
它非常适合用来做指针运算、地址偏移等操作。
基本语法
LEA destination, source
- destination:必须是一个寄存器(如
eax
,ebx
等) - source:是一个有效的内存地址表达式,如
[ebx + ecx*4 + 8]
实际示例
lea eax, [ebx + ecx*4 + 8]
假设:
ebx = 1000
ecx = 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
是传入的索引i
lea 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 个汉字, 你数一下对不对.
相关文章:
- 简易教程: C++的智能指针 C++ 智能指针教程 C++ 中的智能指针提供了自动且安全的内存管理。它们通过 RAII(资源获取即初始化)机制,帮助开发者避免内存泄漏和悬空指针的问题,确保对象在生命周期结束时被正确释放。 本教程将介绍 C++ 中三种主要的智能指针: std::unique_ptr:独占式所有权 std::shared_ptr:共享式所有权 std::weak_ptr:非拥有式弱引用 1. std::unique_ptr unique_ptr 拥有独占所有权。一个资源只能被一个...
- 写在教娃编程视频300天 时间过得好快, 第300天了. 其中因为打COVID辉瑞疫苗第2针后反应很大暂停了一周, 还有几天娃不在状态暂更, 其它时间我都会带着娃坚持做这一件事. 回顾第一天: 还记得当时只是上传到我的油管帐号 DoctorLai, 当时还在AMAZON, 第二天例会的时候便和团队分享了, 当时同事还说我能在5分钟内讲清楚递归很厉害, 而且我的方法很特别. 后来就一稿多投到了B站 justyyuk 反而B站更受欢迎一些....
- 按揭贷款(房贷,车贷) 每月还贷计算器 去年给银行借了17万英镑 买了20万7500英镑的房子, 25年还清. 前2年是定率 Fix Rate 的合同 (年利率2.49%). 每个月大概是还 700多英镑. 有很多种还贷的计算方式, 定率/每月固定 是比较常用的. 简单来说就是 每个月交的钱是...
- Javascript 中 sleep 函数实现 Javascript 中并没有 built-in 的 sleep 函数支持, 在 async/await/Promise 的支持之前, 我们可以用 busy-waiting 的方式来模拟: function sleep( milliseconds...
- 智能手机 HTC One M9 使用测评 虽然我对手机要求不高, 远远没有像追求VPS服务器一样, 但是怎么算来两年内换了四个手机, 先是三星 S4 用了一年多, 然后 Nokia Lumia 635 Windows Phone, 后来又是 BLU, 半年多前换了...
- 《Steem 指南》之 justyy 在线工具与 API 系列 – 同时给多个帐号发送SBD或者STEEM 同时给多个帐号发送SBD或者STEEM STEEMIT 和 BUSY 的前端都有一个内置的钱包工具, 您可以一次给一个帐号发送 SBD 或者 STEEM. 当我们要给很多很多人发送钱的时候, 就显得有些不方便了. 这时候可以用这个在线工具: https://steemyy.com/wallet-tool/ 填写表单 只需要填上你的ID,...
- 快通过 PAYPAL ME 捐点给我吧 PAYPAL在西方国家 很是流行 国内的山寨PAYPAL就是支付宝. PAYPAL 的好处就是 在英国和银行转帐 免费的. 转帐的速度很快. 几乎是几秒就转到了我的HALIFAX银行. PAYPAL和EBAY还真是一伙的 之前在EBAY上卖 需要交 10%的费用 PAYPAL费用 还有EBAY的上架费....
- 借助AI快速开源了三个小工具: 写代码越来越像做产品了, AI 真把我宠坏了(Vibe Coding) 程序员的未来?Vibe Coding + AI 一起上! 借助 AI 快速开源了三个小工具 最近,我利用 ChatGPT-4o 和 o4-mini 快速开发并开源了三个小工具。起因其实很简单——每次想转换 YAML/JSON 或进行...