在上一章中,我们介绍了一些汇编语言指令。汇编语言中有多种类型的指令,这些指令可以通过分组来更清晰地了解特定指令集的功能和目的。为了理解在逆向工程中逐条分析基础汇编指令的意义,我们将举一个现实生活中的例子。
你小时候有没有拆过玩具?打开玩具,查看其内部组件总是很有趣。如今,如果你需要了解玩具的内部工作原理,首先要理解安装在玩具硬件设计中的各个组件。要揭示玩具的内部运行机制,就必须掌握其中每个组件的工作原理。整个过程在某种程度上类似于对玩具的逆向工程。
同理,要对任何软件或应用进行逆向工程,我们需要将其反汇编成不同的指令,并对这些反汇编得到的汇编指令进行理解。因此,要了解任何软件或应用的工作原理,就需要清晰掌握各条指令及其执行路径。这就要求我们理解汇编语言中不同类型的指令。
章节结构
本章将涵盖以下主题:
- 不同的汇编语言指令
- 汇编指令的语法
- 汇编指令的分组
学习目标
通过本章学习,你将能够理解逆向工程中常用的重要汇编指令,并了解这些指令如何被分组以便于理解,还会结合示例加深印象。我们还将学习指令的语法、它们的内部工作原理,以及不同类型指令背后的基本概念。
不同的汇编语言指令
指令是汇编代码的基本构建块。指令由操作码(opcode)与零个或多个操作数(operand)组成。

操作码通常称为 opcode。操作数可以分为三种类型:
- 立即数操作数(Immediate operands) :固定的十六进制数值,如
0x0A
。 - 寄存器操作数(Register operands) :可以是任意寄存器,如
ECX
、EAX
等。 - 内存地址操作数(Memory address operands) :表示内存地址,写在方括号内,如
[EAX]
。
程序代码以操作码(opcode)和操作数交替的形式按顺序存储在内存中,保存在连续的内存位置中。如下图所示:
- 指令 1 占用两个内存位置,
- 指令 2 也占用两个内存位置,
- 指令 3 仅占用一个内存位置。

看看下面这个带有寄存器操作数的汇编指令示例:
指令格式:
OPERATION_CODE DESTINATION_OPERAND SOURCE_OPERAND
示例:
MOV EAX, ECX
- OPERATION_CODE = MOV,表示"移动"
- DESTINATION_OPERAND = EAX,目标寄存器
- SOURCE_OPERAND = ECX,源寄存器
此指令将 ECX 寄存器中的数据移动到 EAX 寄存器。每条指令所对应的操作码(opcode)告诉 CPU 程序要执行何种操作。上述指令的操作码为 89 C8
,这是其十六进制表示。反汇编器会将这些操作码转换成人类可读的汇编语句,因此 89 C8
会被译为 MOV EAX, ECX
。
既然我们已经掌握了汇编指令的概念,接下来要介绍在逆向工程中常见的主要汇编指令,并将它们按功能分组以便理解。大致可分为以下几类:
- 栈操作指令
- 数据传输指令
- 算术指令
- 程序执行指令
- 分支指令
- 位操作指令
- 处理器控制指令
- 字符串指令
下面我们将逐一查看每个类别,了解其中包含的汇编指令。
栈操作指令
这些是用于在栈上进行数据传输的通用指令。
PUSH
指令格式:
PUSH SOURCE_OPERAND
含义:
将源操作数的值复制到栈顶,并将 ESP 寄存器减小相应字节数。
影响标志: 无
PUSHAD
指令格式:
PUSHAD
含义:
按顺序将所有通用寄存器的值压入栈中,顺序为:EAX、ECX、EDX、EBX、ESP、EBP、ESI、EDI。
影响标志: 无
PUSHFD
指令格式:
PUSHFD
含义:
将 EFLAGS(标志寄存器)的值压入栈中。
影响标志: 无
POP
指令格式:
POP DESTINATION_OPERAND
含义:
从栈顶弹出一个值,并复制到目标操作数;然后将 ESP 寄存器增大相应字节数。
影响标志: 无
POPAD
指令格式:
POPAD
含义:
按顺序从栈中弹出值并写入寄存器,顺序为:EDI、ESI、EBP、ESP(该值会被忽略)、EDX、ECX、EAX。
影响标志: 无
POPFD
指令格式:
POPFD
含义:
从栈顶弹出一个双字(DWORD)并写入 EFLAGS(标志寄存器)。
影响标志: 无
RET
指令格式:
css
RET [nBytes]
含义:
函数返回指令,将控制权从被调用者(callee)转移回调用者(caller)------即跳转到保存在栈上的返回地址。可选的 nBytes
表示在返回时额外清理栈上 n
字节的参数空间。
影响标志: 无
数据传输指令
这些是用于数据传输操作的通用指令。
MOV
指令格式:
MOV 目标操作数, 源操作数
含义:
将源操作数中的数据复制到目标操作数中,并将结果存储在目标操作数。
影响标志: 无
LEA
指令格式:
LEA 寄存器, 操作数
含义:
LEA(Load Effective Address)将操作数的有效地址加载到指定寄存器中。
影响标志: 无
XCHG
指令格式:
objectivec
XCHG 目标操作数, 源操作数
含义:
交换源操作数和目标操作数中的值。
影响标志: 无
CMPXCHG
指令格式:
objectivec
CMPXCHG 目标操作数, 源操作数
含义:
用于比较并交换。首先将 EAX 与目标操作数比较:
- 如果 EAX == 目标操作数,则将源操作数的值加载到目标操作数。
- 如果 EAX != 目标操作数,则将目标操作数的值加载到 EAX。
影响标志: CF、ZF、SF、AF、PF、OF
LAHF
指令格式:
LAHF
含义:
将标志寄存器的状态复制到 AH 寄存器中。仅将以下 5 位复制到 AH 的位 7、6、4、2 和 0;AH 的位 5、3 和 1 将保持不变。
执行此指令后,AH 寄存器的位状态:

影响标志: 无
SAHF
指令格式:
SAHF
含义:
将 AH 寄存器的位(7、6、4、2、0)存入标志寄存器,对应更新 SF、ZF、AF、PF 和 CF。
影响标志: SF、ZF、AF、PF、CF
LAR
指令格式:
LAR 目标操作数, 源操作数
含义:
从源操作数指定的段描述符中加载有效权限位到目标操作数。
影响标志: ZF
MOVSX
指令格式:
MOVSX 目标操作数, 源操作数
含义:
带符号扩展移动:将源操作数复制到目标操作数,并用符号位(最高位)填充目标寄存器中多余的高位。
影响标志: 无
MOVZX
指令格式:
MOVZX 目标操作数, 源操作数
含义:
带零扩展移动:将源操作数复制到目标操作数,并用 0 填充目标寄存器中多余的高位。
影响标志: 无
XLAT
指令格式:
XLAT
含义:
表查找(Translate):以 AL 寄存器作为无符号索引,将 AL 设置为 DS:[EBX + AL]。其中 EBX 保存表的基地址。
MOVS
指令格式:
MOVS 目标字符串, 源字符串
含义:
将数据(Byte、WORD、DWORD)从源字符串复制到目标字符串,其中:
- 源字符串(SOURCE_STRING) 由 DS:SI(或 ESI)指向
- 目标字符串(DESTINATION_STRING) 由 ES:DI(或 EDI)指向
- SI 是数据段(DS)中的偏移地址
- DI 是附加段(ES)中的偏移地址
影响标志: 无
算术指令
以下指令用于汇编语言中的算术运算。
AAA
指令格式:
AAA
含义:
ASCII 加法调整(ASCII Adjust after Addition)。用于对两个"未打包"BCD 数(ASCII 码 '0'--'9' 即 0x30--0x39)执行 ADD 后,将结果转换为两位 BCD。
影响标志: AF、CF;(SF、ZF、OF、PF 未定义)
示例:
ini
XOR AH, AH ; 清零 AH
MOV AL, 32h ; AL = ASCII '2'
ADD AL, 39h ; AL = 0x6B(ASCII 9 + ASCII 2 不是 ASCII)
AAA ; 调整后 AH = 0x01, AL = 0x01,AX = 0x0101
AAS
指令格式:
AAS
含义:
ASCII 减法调整(ASCII Adjust after Subtraction)。用于对两个"未打包"BCD 数执行 SUB 后,将结果转换为两位 BCD。
影响标志: AF、CF;(SF、ZF、OF、PF 未定义)
AAD
指令格式:
AAD
含义:
ASCII 除法调整(ASCII Adjust before Division)。用于在 DIV 之前,将 AH:AL 中的"未打包"BCD 数转换为二进制,商放入 AL,余数放入 AH,均为"未打包"BCD。
影响标志: PF、SF、ZF
示例(68 ÷ 8):
ini
MOV AX, 0608h ; AH=0x06, AL=0x08
MOV CH, 08h ; 除数 ASCII '8'
AAD ; AX = 0044h (BCD 44,即十进制 68)
DIV CH ; AL = 08 (商), AH = 04 (余)
AAM
指令格式:
AAM
含义:
ASCII 乘法调整(ASCII Adjust after Multiplication)。用于对两个"未打包"BCD 数执行 MUL 后,将结果(存于 AX)拆分为 AH, AL 两个"未打包"BCD。
影响标志: PF、SF、ZF
示例(7 × 5):
ini
MOV AL, 07h ; AL = 0x07
MOV BH, 05h ; BH = 0x05
MUL BH ; AX = 0x0023 (十进制 35)
AAM ; AX = 0203h (AH=02, AL=03)
ADC
指令格式:
ADC 目标, 源
含义:
带进位加法。计算 目标 + 源 + CF,结果存回目标。
影响标志: AF、CF、OF、PF、SF、ZF
ADD
指令格式:
sql
ADD 目标, 源
含义:
加法。计算 目标 + 源,结果存回目标。
影响标志: AF、CF、OF、PF、SF、ZF
CMP
指令格式:
objectivec
CMP 目标, 源
含义:
比较。执行 目标 -- 源,但不保存结果,仅更新标志以供后续分支等指令使用。
影响标志: AF、CF、OF、PF、SF、ZF
DAA
指令格式:
DAA
含义:
BCD 加法调整(Decimal Adjust after Addition)。在对 AL 执行 ADD/ADC 后,用于将结果调整为 BCD 形式,仅作用于 AL。
影响标志: AF、CF;(OF、PF、SF、ZF 未定义)
示例:
ini
MOV DX, 1122h ; 加载 BCD 1122
MOV BX, 3088h ; 加载 BCD 3088
MOV AL, BL ; 将低字节 88h 装入 AL
ADD AL, DL ; 执行 AL + DL
DAA ; BCD 调整后的结果存回 AL
DAS
指令格式:
DAS
含义:
BCD 减法调整(Decimal Adjust after Subtraction)。在对 AL 执行 SUB/SBB 后,用于将结果调整为 BCD 形式,仅作用于 AL。
影响标志: AF、CF;(OF、PF、SF、ZF 未定义)
示例:
css
MOV DX, 1122h
MOV BX, 3088h
MOV AL, BL
SUB AL, DL
DAS ; BCD 调整后的结果存回 AL
DEC
指令格式:
sql
DEC 目标
含义:
目标减 1,结果存回目标(寄存器或内存)。
影响标志: AF、OF、PF、SF、ZF
示例:
ini
MOV EAX, 02h
DEC EAX ; EAX = 01h
DIV
指令格式:
css
DIV 源
含义:
无符号除法:将 AX、DX:AX 或 EDX:EAX 作为被除数,分别按 BYTE、WORD、DWORD 大小除以源操作数(BYTE/WORD/DWORD)。
- BYTE ÷ BYTE:被除数在 AL,结果商放 AL,余数放 AH。
- WORD ÷ WORD:被除数在 DX:AX(高 WORD 在 DX,低 WORD 在 AX),商放 AX,余数放 DX。
- DWORD ÷ DWORD:被除数在 EDX:EAX(高 DWORD 在 EDX,低 DWORD 在 EAX),商放 EAX,余数放 EDX。
影响标志: 无
示例:
css
MOV DX, 0
MOV AX, 8003h
MOV CX, 0100h
DIV CX ; AX = 0080h, DX = 0003h
IDIV
指令格式:
IDIV 源
含义:
有符号除法;与 DIV 相同,但对被除数和商、余数进行有符号处理。
影响标志: 无
MUL
指令格式:
MUL 源
含义:
无符号乘法:将 AL、AX 或 EAX(被乘数)与源操作数(BYTE/WORD/DWORD)相乘,结果存于 AX、DX:AX 或 EDX:EAX。
- BYTE × BYTE:AL × 源 → AX(高 8 位 AH,低 8 位 AL)。
- WORD × WORD:AX × 源 → DX:AX(高 WORD 在 DX,低 WORD 在 AX)。
- DWORD × DWORD:EAX × 源 → EDX:EAX(高 DWORD 在 EDX,低 DWORD 在 EAX)。
影响标志: OF、CF
示例:
ini
MOV AX, 8003h
MOV CX, 0100h
MUL CX ; AX = 0300h, DX = 0080h
IMUL
指令格式:
IMUL 源
含义:
有符号乘法;用有符号规则进行乘法运算,其余与 MUL 相同。
影响标志: OF、CF
INC
指令格式:
INC 目标
含义:
目标加 1,结果存回目标(寄存器或内存)。
影响标志: AF、OF、PF、SF、ZF
示例:
ini
MOV EAX, 02h
INC EAX ; EAX = 03h
NEG
指令格式:
NEG 目标
含义:
取目标的二进制补码(符号取反):执行 0 -- 目标,然后采用二补码保存结果。
影响标志: AF、OF、PF、SF、ZF
示例:
ini
MOV EAX, 02h
NEG EAX ; EAX = FFFFFFFEh (-2)
SBB
指令格式:
SBB 目标, 源
含义:
带借位减法:计算 目标 -- 源 -- CF,结果存回目标。
影响标志: AF、CF、OF、PF、SF、ZF
SUB
指令格式:
vbnet
SUB 目标, 源
含义:
减法:计算 目标 -- 源,结果存回目标。
影响标志: AF、CF、OF、PF、SF、ZF
XADD
指令格式:
XADD 目标, 源
含义:
先执行加法(如 ADD),将结果存入目标;然后将原目标值复制回源。
影响标志: AF、CF、OF、PF、SF、ZF
示例:
ini
MOV EAX, 00000001h
MOV EBX, 00000002h
XADD EAX, EBX ; EAX = 00000003h, EBX = 00000001h
程序执行指令
这些指令用于控制程序执行流程及标志的更新。
CALL
指令格式:
objectivec
CALL 目标操作数
含义:
在程序执行中,当一个函数调用另一个函数时使用 CALL
。执行时,指令指针跳转到被调用过程(callee)的代码。CPU 会将 CALL
指令后下一条指令的地址压入栈中,作为返回地址;被调用过程执行完毕后,通过 RET
指令弹出该地址,返回到调用者(caller)继续执行。
影响标志: 无
示例:
ini
CALL PROC_LABEL ; 跳转到标号 PROC_LABEL 所在的过程
ENTER
指令格式:
ENTER 存储字节数, 嵌套级别
含义:
用于创建过程栈帧,分配存储空间并处理嵌套级别。适用于支持块结构语言(如 C、Pascal)的过程调用。
- 存储字节数:在栈上预留的字节数。
- 嵌套级别 :从 0 到 31,表示过程调用的嵌套深度。
影响标志: 无
LEAVE
指令格式:
LEAVE
含义:
用于释放由 ENTER
创建的过程栈帧,恢复 (E)SP/(E)BP
,准备 RET
返回。
影响标志: 无
INT
指令格式:
sql
INT <类型>
含义:
软件中断指令,显式触发中断处理。<类型>
为 0--255 的中断号。执行时:
- 将 FLAGS 寄存器压栈;
- 将 CS(代码段寄存器)压栈;
- 将
INT
指令后下一条指令的偏移地址压栈; - 从
类型 × 4
的内存地址处读取新的 IP(指令指针)并加载; - 从
(类型 × 4) + 2
处读取新的 CS; - 清除 TF(陷阱标志)和 IF(中断标志);
跳转到中断服务例程(ISR)执行。
影响标志: IF、TF
INTO
指令格式:
sql
INTO
含义:
溢出中断(Interrupt on Overflow):若 OF(溢出标志)置位,则行为同 INT 4
,触发中断;否则继续顺序执行。流程与 INT
类似:
- 压栈 FLAGS、CS、返回地址;
- 从
4 × 4
处读取新 IP; - 从
4 × 4 + 2
处读取新 CS; - 清除 IF、TF。
影响标志: IF、TF
IRET
指令格式:
IRET
含义:
中断返回(Interrupt Return):结束中断服务例程,将栈上的 IP、CS 和 FLAGS 依次弹出,恢复到中断前的执行状态,继续被中断的程序。
影响标志: AF、CF、DF、IF、ZF、SF、TF、PF
LOOP
指令格式:
vbnet
LOOP 目标
含义:
将 (E)CX 寄存器减 1;若新值非零,则跳转到指定目标;否则顺序执行下一条指令。
影响标志: 无
示例:
ini
LOOP MEM_LOC ; ECX 减 1 后若非零,则跳转到 MEM_LOC
LOOPE / LOOPZ
指令格式:
ini
LOOPE 目标 ; 或 LOOPZ 目标
含义:
将 (E)CX 减 1;若新值非零且 ZF=1,则跳转到目标;否则继续执行下一条。
影响标志: 无
LOOPNE / LOOPNZ
指令格式:
ini
LOOPNE 目标 ; 或 LOOPNZ 目标
含义:
将 (E)CX 减 1;若新值非零且 ZF=0,则跳转到目标;否则继续执行下一条。
影响标志: 无
TEST
指令格式:
TEST 目标操作数, 源操作数
含义:
对目标和源执行按位 AND 操作,但不保存结果,仅更新 SF、ZF、PF 标志。常用于检查寄存器或内存是否为零,而不修改其值。
影响标志: SF、ZF、PF
示例:
ini
TEST EAX, 01h ; 若 EAX=01h,则 ZF=0
TEST EAX, 02h ; 若 EAX=01h,则 ZF=1
TEST EAX, EAX ; 检查 EAX 是否为零
分支指令
分支指令用于控制代码执行的流程。x86 中有两类跳转:
-
无条件跳转(Unconditional jump) :指令指针直接跳转到指定位置。
-
条件跳转(Conditional jump) :在评估某个条件后,若满足则跳转,否则继续顺序执行。常配合下列两条指令设置标志:
- TEST:按位与,不保存结果,仅影响标志。
- CMP:相减,不保存结果,仅影响标志。
说明 :分支指令中的 DESTINATION_OPERAND 通常也称为标签(LABEL)或目标地址(DESTINATION ADDRESS),可以是相对于当前指令的位移,也可以是绝对地址。
JMP
JMP 目标
含义 :无条件跳转到指定目标。
影响标志 :无
示例:
ini
JMP PROC_LABEL ; 跳转到 PROC_LABEL
JZ / JE
ini
JZ 目标 ; 等同 JE
含义 :若 ZF=1(零标志置位),则跳转;否则继续执行下一条指令。
影响标志 :无
示例:
ini
JZ MEM_LOC ; 若 ZF=1,则跳转
JNZ / JNE
ini
JNZ 目标 ; 等同 JNE
含义 :若 ZF=0(零标志清零),则跳转;否则顺序执行。
示例:
ini
JNZ MEM_LOC ; 若 ZF=0,则跳转
JG / JA
ini
JG 目标 ; 有符号大于
JA 目标 ; 无符号以上(等同 JG 对应无符号)
含义 :常配合 CMP
后使用。
- JG(Jump if Greater):若有符号比较结果"目标 > 源",则跳转。
- JA (Jump if Above):若无符号比较结果"目标 > 源",则跳转。
示例:
ini
CMP EAX, 02h
JG MEM_LO ; 若 EAX(有符号)> 2,跳转
JA MEM_LO ; 若 EAX(无符号)> 2,跳转
JGE / JAE
ini
JGE 目标 ; 有符号 ≥
JAE 目标 ; 无符号 ≥
含义:
- JGE:若有符号"目标 ≥ 源",跳转。
- JAE :若无符号"目标 ≥ 源",跳转。
示例:
ini
CMP EAX, 02h
JGE MEM_LO ; 若 EAX ≥ 2,跳转
JAE MEM_LO ; 若 EAX(无符号)≥ 2,跳转
JL / JB
ini
JL 目标 ; 有符号 <
JB 目标 ; 无符号 <(等同 JL 对应无符号)
含义:
- JL:若有符号"目标 < 源",跳转。
- JB :若无符号"目标 < 源",跳转。
示例:
ini
CMP EAX, 02h
JL MEM_LO ; 若 EAX < 2,跳转
JB MEM_LO ; 若 EAX(无符号)< 4,跳转
JLE / JBE
ini
JLE 目标 ; 有符号 ≤
JBE 目标 ; 无符号 ≤
含义:
- JLE:若有符号"目标 ≤ 源",跳转。
- JBE :若无符号"目标 ≤ 源",跳转。
示例:
ini
CMP EAX, 02h
JLE MEM_LO ; 若 EAX ≤ 2,跳转
JBE MEM_LO ; 若 EAX(无符号)≤ 4,跳转
JO
JO 目标
含义 :若 OF=1(溢出标志置位),则跳转;否则继续。
示例:
ini
ADD AL, BL
JO MEM_LOC ; 若加法溢出,跳转
JS
JS 目标
含义 :若 SF=1(符号标志置位),则跳转;否则继续。
示例:
ini
ADD AL, BL
JS MEM_LOC ; 若结果为负,跳转
JECXZ
JECXZ 目标
含义 :若 ECX=0,则跳转;否则继续。
示例:
ini
JECXZ MEM_LOC ; 若 ECX=0,跳转
位操作指令
以下指令用于位级操作。在介绍这些指令之前,我们先回顾一下真值表:

BSWAP
指令格式:
BSWAP 寄存器32
含义:
将寄存器中的字节顺序在大端与小端之间互换。
影响标志: 无
示例:
ini
MOV EAX, 87654321h ; EAX = 0x87654321
BSWAP EAX ; EAX = 0x21436587
AND
指令格式:
AND 目标操作数, 源操作数
含义:
对目标操作数和源操作数执行按位与运算,结果存回目标操作数。
影响标志: CF、OF、PF、SF、ZF
示例:
ini
MOV EAX, 87654321h ; EAX = 0x87654321
MOV EBX, 21436587h ; EBX = 0x21436587
AND EAX, EBX ; EAX = 0x01414101
NOT
指令格式:
NOT 目标操作数
含义:
对目标操作数执行按位取反(取一补码),所有 1 变为 0,所有 0 变为 1。
影响标志: 无
示例:
ini
MOV EAX, 12121212h ; EAX = 0x12121212
NOT EAX ; EAX = 0xEDEDEDED
OR
指令格式:
OR 目标操作数, 源操作数
含义:
对目标操作数和源操作数执行按位或运算,结果存回目标操作数。
影响标志: CF、OF、PF、SF、ZF
示例:
ini
MOV EAX, 87654321h ; EAX = 0x87654321
MOV EBX, 21436587h ; EBX = 0x21436587
OR EAX, EBX ; EAX = 0xA76767A7
XOR
指令格式:
vbnet
XOR 目标操作数, 源操作数
含义:
对目标操作数和源操作数执行按位异或运算,结果存回目标操作数。
影响标志: CF、OF、PF、SF、ZF
示例:
ini
MOV EAX, 87654321h ; EAX = 0x87654321
XOR EAX, EAX ; EAX = 0x00000000
RCL
指令格式:
RCL 目标操作数, 计数
含义:

通过进位左循环移位(RCL)
RCL 指令通过 CF 标志将目标操作数中的位从右到左循环移动 n 次。每次循环时,最高有效位(MSB)移入 CF 标志,而原 CF 标志则进入最低有效位(LSB)。
-
影响标志:CF、OF
-
示例:
iniMOV EAX, 01H ; EAX = 00000001H, CF = 0 RCL EAX, 2 ; 对 EAX 执行两次循环左移,结果 EAX = 0x00000004
通过进位右循环移位(RCR)
RCR 目标操作数, 计数
含义:
RCR 指令通过 CF 标志将目标操作数中的位从左到右循环移动指定次数。每次循环时,最低有效位(LSB)移入 CF 标志,而原 CF 标志则进入最高有效位(MSB)。
影响标志: CF、OF

通过进位右循环移位(RCR)
RCR 指令通过 CF 标志将目标操作数中的位从左向右循环移动指定次数。每次循环时,最低有效位(LSB)移入 CF 标志,而原 CF 标志则进入最高有效位(MSB)。
-
影响标志:CF、OF
-
示例:
iniMOV EAX, 01H ; EAX = 00000001H,CF = 0 RCR EAX, 2 ; 对 EAX 执行两次通过进位右循环移位,结果 EAX = 0x80000000
循环左移(ROL)
ROL 目标操作数, 计数
含义:
循环左移(ROL)
ROL 指令将目标操作数中的位从右向左循环移动指定次数(n 次),最后一次移出的位值会存入 CF 标志。
-
影响标志:CF、OF
-
示例:
iniMOV EAX, 40000001h ; EAX = 0x40000001, CF = 0 ROL EAX, 2 ; 循环左移 2 位后,EAX = 0x00000005,CF = 1
循环右移(ROR)
ROR 目标操作数, 计数
含义:
将目标操作数中的位从左向右循环移动指定次数(n 次),最后一次移出的位值会存入 CF 标志。
- 影响标志:CF、OF

循环右移(ROR)
ROR 指令将目标操作数中的位从左向右循环移动指定次数(n 次),最后一次移出的位值会存入 CF 标志。
-
影响标志:CF、OF
-
示例:
iniMOV EAX, 40000001h ; EAX = 0x40000001, CF = 1 ROR EAX, 2 ; 循环右移 2 位后,EAX = 0x50000000, CF = 0
逻辑右移(SHR)
SHR 目标操作数, 计数
含义:
逻辑右移指令将目标操作数的位向右移动指定次数(n 次),高位填充零,最低位移出的位存入 CF 标志。
-
影响标志:CF、ZF、SF、PF
-
示例:
iniMOV EAX, 80000000h ; EAX = 0x80000000 SHR EAX, 1 ; 逻辑右移 1 位后,EAX = 0x40000000, CF = 0

逻辑右移(SHR)
SHR 指令将目标操作数的位从左向右逻辑移动指定次数(n 次),每次移出的最低位存入 CF 标志;由于是逻辑右移,最高位总是补零。
-
影响标志: CF、OF、PF、SF、ZF(AF 未定义)
-
示例:
iniMOV EAX, 40000001h ; EAX = 0x40000001, CF = 0 SHR EAX, 2 ; 逻辑右移 2 位后,EAX = 0x10000000, CF = 0
逻辑左移(SHL)
SHL 目标操作数, 计数
含义:
逻辑左移指令将目标操作数的位从右向左逻辑移动指定次数(n 次),每次移出的最高位存入 CF 标志;最低位总是补零。
-
影响标志: CF、OF、PF、SF、ZF(AF 未定义)
-
示例:
iniMOV EAX, 00000001h ; EAX = 0x00000001, CF = 0 SHL EAX, 2 ; 逻辑左移 2 位后,EAX = 0x00000004, CF = 0
附注: 有关位移操作的详细说明,请参见附录中的"位移"部分。

逻辑左移(SHL)
SHL 指令将目标操作数的位从右向左逻辑移动指定次数(n 次),每次移出的最高位存入 CF 标志;由于是逻辑移位,最低位总是补零。
-
影响标志: CF、OF、PF、SF、ZF(AF 未定义)
-
示例:
iniMOV EAX, 40000001h ; EAX = 0x40000001, CF = 0 SHL EAX, 2 ; 逻辑左移 2 位后,EAX = 0x00000004, CF = 1
算术右移(SAR)
SAR 目标操作数, 计数
含义:
算术右移指令将目标操作数的位从左向右移动指定次数(n 次),最低位移出后存入 CF 标志;最高位按原符号位(MSB)填充,以保持有符号数的正负意义。
-
影响标志: CF、OF、PF、SF、ZF(AF 未定义)
-
示例:
iniMOV EAX, 80000004h ; EAX = 0x80000004, CF = 0 SAR EAX, 2 ; 算术右移 2 位后,EAX = 0xE0000001, CF = 0

算术右移(SAR)将目标操作数的位从左向右移动指定次数(n 次),每次移出的最低位存入 CF 标志;由于是算术移位,最高位由原 MSB(符号位)决定。
-
影响标志: CF、OF、PF、SF、ZF(AF 未定义)
-
示例:
iniMOV EAX, 40000001h ; EAX = 0x40000001, CF = 1 SAR EAX, 2 ; 算术右移 2 位后,EAX = 0x10000000, CF = 0
算术左移(SAL)
SAL 目标操作数, 计数
含义:
SAL 即算术左移,其行为与逻辑左移(SHL)相同:将位从右向左移动指定次数,移出的最高位存入 CF,最低位补零。
- 影响标志: CF、OF、PF、SF、ZF(AF 未定义)

算术左移(SAL)将目标操作数的位从右向左移动指定次数(n 次),每次移出的最高位存入 CF 标志;由于是算术移位,最低位始终补零。
-
影响标志: CF、OF、PF、SF、ZF(AF 未定义)
-
示例:
iniMOV EAX, 40000001h ; EAX = 0x40000001, CF = 0 SAL EAX, 2 ; 算术左移 2 位后,EAX = 0x00000004, CF = 1
双操作数逻辑左移(SHLD)
SHLD 目标操作数, 源操作数, 计数
含义:
将目标操作数和源操作数组合视为一个较长的双操作数结构,然后对该结构执行逻辑左移。移动时,从目标操作数的右端填入源操作数的高位,最后移出的位存入 CF 标志;左移时,在最低位补零。常用于跨寄存器的位字段操作。

双操作数逻辑左移(SHLD)将目标操作数的位从右向左移动指定次数(n 次),目标操作数中留下的空位由源操作数中移出的高位填充;最后一次从目标操作数中移出的位存入 CF 标志。源操作数本身不会被修改。
-
影响标志: CF、OF、PF、SF、ZF(AF 未定义)
-
示例:
iniMOV EAX, 40000001h ; EAX = 0x40000001,CF = 0 MOV EBX, 50000001h ; EBX = 0x50000001,CF = 0 SHLD EAX, EBX, 2 ; EAX = 0x00000005(原 EAX 左移两位) ; 再填入 EBX 的高两位:EAX = 0x50000001 ; CF = 1(最后从 EAX 移出的位)
双操作数逻辑右移(SHRD)
SHRD 目标操作数, 源操作数, 计数
含义:
将目标操作数的位从左向右逻辑移动指定次数(n 次),目标操作数中留下的空位由源操作数中移出的低位填充;最后一次从目标操作数中移出的位存入 CF 标志。源操作数本身不会被修改。

双操作数逻辑右移(SHRD)
SHRD 将目标操作数的位从左向右逻辑移动指定次数(n 次),目标操作数中留下的空位由源操作数中移出的低位填充;最后一次从目标操作数中移出的位存入 CF 标志。源操作数本身不受影响。
-
影响标志: CF、OF、PF、SF、ZF(AF 未定义)
-
示例:
iniMOV EAX, 40000001h ; EAX = 0x40000001,CF = 1 MOV EBX, 50000001h ; EBX = 0x50000001,CF = 1 SHRD EAX, EBX, 2 ; EAX = 0x50000000(右移两位后填入 EBX 低位) ; 最终 EAX = 0x50000001,CF = 0
处理器控制指令
以下指令用于控制处理器的运行状态。
CLC
objectivec
CLC
Clear Carry Flag(清除进位标志) :将 CF 置 0。
-
影响标志: CF
-
示例:
iniMOV EAX, 40000001h ; CF = 0 SAL EAX, 2 ; 执行 SAL 后 CF = 1 CLC ; 清除 CF,CF = 0
CLD
objectivec
CLD
Clear Direction Flag(清除方向标志) :将 DF 置 0。
- 影响标志: DF
CLI
objectivec
CLI
Clear Interrupt Flag(清除中断标志) :将 IF 置 0,使处理器不响应外部中断。
- 影响标志: IF
CMC
objectivec
CMC
Complement Carry(翻转进位标志) :将 CF 取反。
-
影响标志: CF
-
示例:
iniMOV EAX, 40000001h SAL EAX, 2 ; CF = 1 CMC ; CF = 0
ESC
ESC 操作码, 源操作数
Escape to Coprocessor(协处理器转义) :将后跟的浮点或数学协处理器指令传递给协处理器执行。CPU 取指令字节并通过数据总线排入协处理器指令队列,直到 ESC 指令触发协处理器解码并执行对应操作。
- 影响标志: 无
LOCK
makefile
LOCK: 指令
LOCK 前缀:在指令前加上 LOCK 时,会拉高处理器的 LOCK 引脚,锁定系统总线。外部总线主控和外围设备在该指令执行完毕前无法使用总线,用于保证多核/多处理环境下关键指令的原子性。
-
影响标志: 无
-
示例:
cssLOCK: MOV EAX, EBX ; 在 MOV 执行期间锁定总线
NOP
NOP
No Operation(无操作) :不执行任何功能,仅占用指令周期。
-
影响标志: 无
-
示例:
iniNOP ; 什么也不做
STC
STC
Set Carry Flag(置位进位标志) :将 CF 置 1。
-
影响标志: CF
-
示例:
iniCLC ; CF = 0 STC ; CF = 1
STD
STD
Set Direction Flag(置位方向标志) :将 DF 置 1。
- 影响标志: DF
STI
STI
Set Interrupt Flag(置位中断标志) :将 IF 置 1,使处理器响应中断请求。恢复系统对中断的处理能力。
- 影响标志: IF
字符串操作指令
以下指令用于处理字符串操作。
CMPS / CMPSB / CMPSW / CMPSD
指令格式:
- CMPSB 源字符串, 目标字符串
- CMPSW 源字符串, 目标字符串
- CMPSD 源字符串, 目标字符串
(CMPS = Compare + String;B = Byte,W = Word,D = DWORD)
含义:
用于比较两段字符串。源字符串由 ESI 指向,目标字符串由 EDI 指向。
- CMPSB :按字节(byte)比较,等同于
CMP BYTE PTR [ESI], [EDI]
; - CMPSW:按字(word)比较;
- CMPSD:按双字(dword)比较。
比较操作即执行 ESI/EDI 指向的字节、字或双字的相减,与 CMP
指令行为一致。
CMPS 指令常与前缀 REPE /REPZ(重复执行直到 ECX=0 或 ZF=0)一起使用。
- 当 DF=0(方向标志清零)时,每次比较后 ESI 和 EDI 分别递增:B → +1,W → +2,D → +4;
- 当 DF=1(方向标志置位)时,每次比较后 ESI 和 EDI 分别递减:B → --1,W → --2,D → --4。
影响标志: AF、CF、OF、PF、SF、ZF
示例:
ini
MOV ECX, Length ; 要比较的元素数量
CLD ; DF=0,向前比较
REPE CMPSB ; 重复比较 ECX 次或直到不等
上述代码按字节比较 [ESI]
与 [EDI]
,直到 ECX 归零或发现不相等处。

字符串操作指令
以下指令用于处理字符串及块输入输出操作。
CMPS/CMPSB/CMPSW/CMPSD
指令格式:
CMPSB
CMPSW
CMPSD
(CMPS = Compare + String;B = Byte,W = Word,D = DWORD)
含义:
比较由 ESI 指向的源字符串与由 EDI 指向的目标字符串:
- CMPSB 按字节比较;
- CMPSW 按字(2 字节)比较;
- CMPSD 按双字(4 字节)比较。
每次比较即执行 CMP [ESI], [EDI]
(相减但不存结果,仅更新标志)。通常与前缀 REPE/REPZ
(重复直至 ECX=0 或 ZF=0)配合使用。
- DF=0 时,比较后 ESI、EDI 分别 +1/ +2/ +4;
- DF=1 时,比较后 ESI、EDI 分别 --1/ --2/ --4。
影响标志: AF、CF、OF、PF、SF、ZF
示例:
ini
MOV ESI, 0x41000001 ; ESI 指向 STRING1
MOV EDI, 0x82000001 ; EDI 指向 STRING2
MOV ECX, 0x08 ; 比较长度 8
CLD ; DF=0,向前比较
REPE CMPSB ; 重复按字节比较,直至 ECX=0 或 ZF=0
IN/INSB/INSW/INSD
含义:
将外设 I/O 端口的数据读入内存或寄存器。
-
寄存器输入:
IN 目的寄存器, 端口地址
- 端口地址在立即数中指定;
- 目的寄存器可为 AL/AX/EAX,决定读取 1/2/4 字节。
示例:
iniIN EAX, 0x80 ; 从端口 0x80 读取双字到 EAX IN AX, 0x80 ; 从端口 0x80 读取字到 AX
-
块(字符串)输入:
INSB INSW INSD
- 端口地址由 DX 指定,内存目标由 EDI 指向;
INSB
每次传输 1 字节,INSW
2 字节,INSD
4 字节;- 通常与前缀
REP
(重复至 ECX=0)一起使用; - DF=0 时 EDI += 1/2/4,DF=1 时 EDI -= 1/2/4。
影响标志: 无
示例:
css
MOV DX, PORT_ADDRESS
MOV EDI, offset STR
INSW ; 从端口 DX 读一个字到 [EDI]
OUT/OUTSB/OUTSW/OUTSD
含义:
将内存或寄存器的数据输出到外设 I/O 端口。
-
寄存器输出:
sqlOUT 端口地址, 源寄存器
- 源寄存器 AL/AX/EAX 决定输出 1/2/4 字节;
示例:
iniOUT 0x80, EAX ; 将 EAX 的双字输出到端口 0x80 OUT 0x80, AX ; 将 AX 的字输出到端口 0x80
- 源寄存器 AL/AX/EAX 决定输出 1/2/4 字节;
-
块(字符串)输出:
OUTSB OUTSW OUTSD
- 端口地址由 DX 指定,数据源由 ESI 指向;
OUTSB
每次传输 1 字节,OUTSW
2 字节,OUTSD
4 字节;- 通常与前缀
REP
一起使用; - DF=0 时 ESI += 1/2/4,DF=1 时 ESI -= 1/2/4。
影响标志: 无
示例:
css
MOV ESI, offset STR
MOV DX, PORT_ADDRESS
OUTSW ; 将 [ESI] 的一个字输出到端口 DX
LODS/LODSB/LODSW/LODSD
指令格式:
LODSB
LODSW
LODSD
含义:
从内存加载字符串到寄存器:
LODSB
→ AL ← [ESI];LODSW
→ AX ← [ESI];LODSD
→ EAX ← [ESI];- DF=0 时 ESI += 1/2/4,DF=1 时 ESI -= 1/2/4。
影响标志: 无
示例:
css
CLD
MOV ESI, offset STR
LODSB ; AL = [ESI]
STOS/STOSB/STOSW/STOSD
指令格式:
STOSB
STOSW
STOSD
含义:
将寄存器中的字符串数据存到内存:
STOSB
→ [EDI] ← AL;STOSW
→ [EDI] ← AX;STOSD
→ [EDI] ← EAX;- DF=0 时 EDI += 1/2/4,DF=1 时 EDI -= 1/2/4。
影响标志: 无
示例:
css
CLD
MOV EDI, offset STR
STOSB ; [EDI] = AL
SCAS/SCASB/SCASW/SCASD
指令格式:
SCASB
SCASW
SCASD
含义:
扫描内存并与寄存器比较:
SCASB
→ 比较 AL 与 [EDI];SCASW
→ 比较 AX 与 [EDI];SCASD
→ 比较 EAX 与 [EDI];- 结果不存储,仅更新标志;
- DF=0 时 EDI += 1/2/4,DF=1 时 EDI -= 1/2/4。
影响标志: 无
示例:
ini
MOV ECX, 100
MOV EDI, offset STR
MOV AL, 0x20 ; 查找空格
REPNE SCASB ; 重复直至 ECX=0 或 ZF=1
MOVS/MOVSB/MOVSW/MOVSD
指令格式:
MOVSB
MOVSW
MOVSD
含义:
从 [ESI] 复制字符串到 [EDI]:
MOVSB
→ 1 字节,MOVSW
→ 2 字节,MOVSD
→ 4 字节,- DF=0 时 ESI/EDI += 1/2/4,DF=1 时 ESI/EDI -= 1/2/4。
影响标志: 无
示例:
ini
MOV ESI, SRC_STR
MOV EDI, DST_STR
MOV ECX, 5
CLD
REP MOVSB ; 复制 5 字节
REP/REPE/REPZ/REPNE/REPNZ
- REP + 字符串指令:重复执行,直至 ECX=0。
- REPE/REPZ:重复执行,直至 ECX=0 或 ZF=0。
- REPNE/REPNZ:重复执行,直至 ECX=0 或 ZF=1。
影响标志: 取决于后跟指令。
示例:
css
MOV ESI, 0x11E8000
MOV EDI, 0x11E8010
MOV ECX, 5
CLD
REP MOVSB ; 从 [ESI] 复制 5 字节到 [EDI]
结论
在本章中,我们详细讲解了逆向工程中常用的主要汇编指令,涵盖了栈操作、数据传输、算术运算、程序执行、分支跳转、位操作、处理器控制以及字符串操作等多种指令类型,并通过示例演示了部分指令的使用方法。
在下一章中,我们将深入探讨基于栈的指令,并讲解代码调用约定的概念。这一概念在逆向工程中极为重要,你在实际逆向过程中会频繁遇到。