🎨 颜色标记说明

  • 粉色:特别重要、主线必掌握、优先复盘的内容。
  • 蓝色:核心概念、术语、分类名。
  • 橙色:需要关注的边界、易错点、注意事项。
  • 绿色:解释类内容、帮助理解知识点。

MOV 与内存读写

MOV 是最常见的数据传送指令,基本形式为:

1
mov 目标操作数, 源操作数
1
2
3
4
mov eax, 12345678h         ; 立即数写入寄存器
mov ebx, eax ; 寄存器写入寄存器
mov eax, dword ptr [addr] ; 从内存读取 4 Byte
mov dword ptr [addr], eax ; 向内存写入 4 Byte

方括号 [] 表示访问该地址指向的内存。没有方括号时,操作的是地址值或普通操作数本身。

操作宽度

当汇编器无法从寄存器推断内存操作数宽度时,需要显式指定:

写法 宽度
byte ptr [eax] 1 Byte
word ptr [eax] 2 Byte
dword ptr [eax] 4 Byte
qword ptr [rax] 8 Byte
1
2
mov byte ptr [eax], 1
mov dword 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 = 00403000hECX = 3,有效地址为:

1
00403000h + 3 × 4 + 10h = 0040301Ch

常见寻址形式

1
2
3
4
5
6
mov eax, [00403000h]       ; 直接地址
mov eax, [ebx] ; 寄存器间接寻址
mov eax, [ebx+10h] ; 基址 + 偏移
mov eax, [ebx+ecx] ; 基址 + 变址
mov eax, [ebx+ecx*4] ; 基址 + 变址 × 比例
mov eax, [ebx+ecx*4+10h] ; 完整形式

数组访问常出现 Index × 元素大小,结构体成员常表现为基址 + 固定偏移。

LEA 与 MOV 的区别

1
2
mov eax, [ebx+ecx*4]  ; 计算地址后,读取该地址中的内容
lea eax, [ebx+ecx*4] ; 只计算地址,不读取内存

LEA 的名字是 Load Effective Address,适合计算指针、数组元素地址,也可能被编译器用于普通算术运算。

判断关键:MOV 配合 [] 取内容,LEA 取得 [] 表达式计算出的地址。

指令限制

常规 MOV 不允许两个显式操作数同时都是普通内存操作数:

1
2
3
4
5
6
; 错误思路
mov [destination], [source]

; 常见写法
mov eax, [source]
mov [destination], eax

立即数可以写入寄存器或内存,但不能作为目标操作数。两个操作数的宽度也必须能够对应。

从反汇编还原数据结构

看到下面的代码:

1
2
3
mov eax, [ecx+8]
mov edx, [ecx+0Ch]
add eax, edx

可以先做出保守判断:

  • ECX 像一个对象或结构体基址;
  • +8+0C 像两个 DWORD 成员偏移;
  • 两个成员被读取后相加。

不要急着给成员命名。先记录基址、偏移、宽度、读写方向,再结合上下文推断语义。

调试练习

  1. 在调试器中给 mov eax, [ebx+ecx*4+10h] 下断点。
  2. 记录 EBX、ECX 的当前值。
  3. 手算有效地址。
  4. 在内存窗口转到该地址。
  5. 比较内存中的 DWORD 与执行后 EAX 的值。

学习检查清单

检查项 状态
能区分地址值与 [] 解引用 待复盘
能使用 BYTE/WORD/DWORD/QWORD 判断访问宽度 待复盘
能计算 Base + Index × Scale + Displacement 待复盘
能说明 MOV 与 LEA 的区别 待复盘
能从成员偏移初步识别结构体访问 待复盘