012、内存—内存读写与寻址
返回:网络安全知识库 · 上一节:内存管理与端序 · 下一节:C 语言与汇编程序框架
MOV 与内存读写
MOV 是最常见的数据传送指令,基本形式为:
1 | mov 目标操作数, 源操作数 |
1 | mov eax, 12345678h ; 立即数写入寄存器 |
方括号
[]表示访问该地址指向的内存。没有方括号时,操作的是地址值或普通操作数本身。
操作宽度
当汇编器无法从寄存器推断内存操作数宽度时,需要显式指定:
| 写法 | 宽度 |
|---|---|
byte ptr [eax] |
1 Byte |
word ptr [eax] |
2 Byte |
dword ptr [eax] |
4 Byte |
qword ptr [rax] |
8 Byte |
1 | mov byte ptr [eax], 1 |
两条指令写入的数值看似相同,但实际覆盖的内存范围不同。
易错点:宽度写错可能覆盖相邻变量,也可能只改到一个多字节变量的低位。
有效地址公式
x86 常见的内存寻址可以概括为:
1 | 有效地址 = Base + Index × Scale + Displacement |
| 部分 | 作用 | 示例 |
|---|---|---|
| Base | 基址寄存器 | ebx |
| Index | 变址寄存器 | ecx |
| Scale | 比例因子,只能是 1、2、4、8 | 4 |
| Displacement | 常量偏移 | 10h |
1 | mov eax, dword ptr [ebx + ecx*4 + 10h] |
如果 EBX = 00403000h、ECX = 3,有效地址为:
1 | 00403000h + 3 × 4 + 10h = 0040301Ch |
常见寻址形式
1 | mov eax, [00403000h] ; 直接地址 |
数组访问常出现 Index × 元素大小,结构体成员常表现为基址 + 固定偏移。
LEA 与 MOV 的区别
1 | mov eax, [ebx+ecx*4] ; 计算地址后,读取该地址中的内容 |
LEA 的名字是 Load Effective Address,适合计算指针、数组元素地址,也可能被编译器用于普通算术运算。
判断关键:MOV 配合
[]取内容,LEA 取得[]表达式计算出的地址。
指令限制
常规 MOV 不允许两个显式操作数同时都是普通内存操作数:
1 | ; 错误思路 |
立即数可以写入寄存器或内存,但不能作为目标操作数。两个操作数的宽度也必须能够对应。
从反汇编还原数据结构
看到下面的代码:
1 | mov eax, [ecx+8] |
可以先做出保守判断:
ECX像一个对象或结构体基址;+8与+0C像两个 DWORD 成员偏移;- 两个成员被读取后相加。
不要急着给成员命名。先记录基址、偏移、宽度、读写方向,再结合上下文推断语义。
调试练习
- 在调试器中给
mov eax, [ebx+ecx*4+10h]下断点。 - 记录 EBX、ECX 的当前值。
- 手算有效地址。
- 在内存窗口转到该地址。
- 比较内存中的 DWORD 与执行后 EAX 的值。
学习检查清单
| 检查项 | 状态 |
|---|---|
能区分地址值与 [] 解引用 |
待复盘 |
| 能使用 BYTE/WORD/DWORD/QWORD 判断访问宽度 | 待复盘 |
| 能计算 Base + Index × Scale + Displacement | 待复盘 |
| 能说明 MOV 与 LEA 的区别 | 待复盘 |
| 能从成员偏移初步识别结构体访问 | 待复盘 |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Ruiqy~!











