现在位置: 首页 > 汇编语言 > 正文

汇编指令速查表

本文以最常见的 x86 架构汇编语言为对象,将常用指令助记符按功能分类整理,方便学习和快速查阅。

指令助记符在不同汇编器(MASM、NASM、GAS)中基本一致,仅在操作数书写格式上略有差异。

九大类指令概览:

分类 指令数量 主要用途
数据传送指令 15 条 在寄存器、内存、I/O 端口之间搬运数据
算术运算指令 18 条 加减乘除、比较及数制调整
逻辑运算与移位指令 14 条 按位与或非异或、移位和循环移位
串操作指令 8 条 处理连续内存区域,配合重复前缀批量操作
控制转移指令 30+ 条 跳转、循环、过程调用与中断
条件设置指令 16 条 根据标志位设置字节值,用于消除分支
输入输出指令 4 条 读写 I/O 端口
处理器控制指令 14 条 控制标志位、同步、系统管理
浮点指令(x87 FPU) 14 条 传统 x87 浮点栈运算

数据传送指令

数据传送指令是最基本的指令类型,负责在寄存器、内存和 I/O 端口之间搬运数据。

大部分传送指令不影响标志位(SAHF、POPF 除外)。

助记符 功能简述
MOV 把源操作数复制到目的操作数,支持寄存器与寄存器、寄存器与内存、立即数到寄存器或内存
MOVSX 带符号扩展的传送,将小尺寸操作数符号扩展为大尺寸(如字节扩展为双字,高位填充符号位)
MOVZX 带零扩展的传送,高位补 0(用于无符号数扩展)
PUSH 将操作数压入堆栈,栈指针 ESP/RSP 自动减小(先减后存)
POP 从堆栈弹出数据到目的操作数,栈指针自动增加(先取后加)
PUSHA / PUSHAD 将所有通用寄存器压栈(16 位用 PUSHA,32 位用 PUSHAD),常用于保存现场
POPA / POPAD 从堆栈恢复所有通用寄存器,与 PUSHA/PUSHAD 对称使用
XCHG 交换两个操作数的内容,至少有一个操作数是寄存器
LEA 取有效地址(Load Effective Address),将源操作数的地址而非内存内容存入目的寄存器,常用于指针计算
LDS / LES / LFS / LGS / LSS 将远指针装入段寄存器与通用寄存器(现代平坦内存模型中较少使用)
LAHF 将标志寄存器的低 8 位装入 AH 寄存器
SAHF 将 AH 寄存器的内容存回标志寄存器的低 8 位
PUSHF / PUSHFD 标志寄存器压栈(16 位用 PUSHF,32 位用 PUSHFD)
POPF / POPFD 从堆栈恢复标志寄存器
XLAT / XLATB 查表翻译指令,将 AL 中的索引值对应内存字节送入 AL,BX/EBX 指向表基址

LEAMOV 的关键区别:LEA REG, [ADDR] 装入的是地址值本身,而 MOV REG, [ADDR] 装入的是该地址处的内存内容。在进行地址计算(如 LEA EAX, [EBX+4*ECX+8])时 LEA 非常高效。


算术运算指令

算术运算指令完成加、减、乘、除以及比较等操作,执行结果会直接影响标志寄存器中的相关标志位。

程序员通常根据运算后的零标志(ZF)、进位标志(CF)、符号标志(SF)和溢出标志(OF)来判断计算结果。

助记符 功能简述
ADD 加法,目的 = 目的 + 源,影响 OF、SF、ZF、CF 等标志位
ADC 带进位加法,目的 = 目的 + 源 + CF,用于多精度算术运算
SUB 减法,目的 = 目的 - 源
SBB 带借位减法,目的 = 目的 - 源 - CF,配合 ADC 用于多精度运算
INC 操作数加 1,不影响 CF 标志
DEC 操作数减 1,不影响 CF 标志
MUL 无符号乘法,被乘数在 AL/AX/EAX,乘积存入 AX/DX:AX/EDX:EAX
IMUL 带符号乘法,支持单操作数、双操作数和三操作数三种形式
DIV 无符号除法,被除数在 AX/DX:AX/EDX:EAX,商和余数存入指定寄存器
IDIV 带符号除法,规则与 DIV 类似但处理符号
CMP 比较两个操作数,执行减法但不保存结果,仅影响标志位(通常后跟条件跳转)
NEG 求补,对操作数取反再加 1,等价于 0 减去操作数
DAA 加法后十进制调整,将 AL 调整为压缩 BCD 码格式
DAS 减法后十进制调整
AAA 加法后 ASCII 调整,用于非压缩 BCD 码
AAS 减法后 ASCII 调整
AAM 乘法后 ASCII 调整
AAD 除法前 ASCII 调整
CBW / CWDE 符号扩展:CBW 将 AL 符号扩展为 AX,CWDE 将 AX 符号扩展为 EAX
CWD / CDQ 符号扩展:CWD 将 AX 扩展为 DX:AX,CDQ 将 EAX 扩展为 EDX:EAX(常用于除法前准备被除数)

有符号运算使用 IMUL / IDIV,无符号运算使用 MUL / DIV。选错指令会导致结果错误——比如同一个二进制值在有符号和无符号解释下代表不同的数值。


逻辑运算与移位指令

这类指令按位进行与、或、非、异或等逻辑操作,以及移位和循环移位。

移位操作常用于快速乘除 2 的幂、位域提取和位掩码操作。

助记符 功能简述
AND 按位与,常用于掩码操作(将特定位清零)
OR 按位或,常用于将特定位置 1
XOR 按位异或,相同位为 0、不同为 1。XOR REG, REG 是清零寄存器的经典高效写法
NOT 按位取反,所有位翻转
TEST 测试位,执行 AND 运算但不保存结果,仅影响标志位(常用于检测某位是否为 0)
SHL / SAL 逻辑左移 / 算术左移,两者功能完全相同,低位补 0,高位移入 CF
SHR 逻辑右移,高位补 0,低位移入 CF(用于无符号数)
SAR 算术右移,高位用原符号位填充,保留数值符号(用于有符号数)
ROL 循环左移,移出的位补回另一侧
ROR 循环右移,移出的位补回另一侧
RCL 带进位循环左移,CF 参与循环(CF 作为临时存储位)
RCR 带进位循环右移,CF 参与循环
SHLD 双精度左移,将目的和源操作数联合左移,结果存入目的
SHRD 双精度右移,将目的和源操作数联合右移,结果存入目的

XOR REG, REG 是清零寄存器的最优方式——生成的机器码比 MOV REG, 0 更短,执行速度也更快。


串操作指令

串操作指令专门处理连续内存区域,搭配重复前缀使用,常用于数组复制、内存比较和缓冲区搜索等批量操作。

这些指令的源地址默认由 DS:ESI 指向,目的地址由 ES:EDI 指向。

助记符 功能简述
MOVS 串传送,将 [DS:ESI] 复制到 [ES:EDI] 并自动更新 ESI、EDI。按操作数大小分为 MOVSB(字节)、MOVSW(字)、MOVSD(双字)
STOS 串存储,将 AL/AX/EAX 存入 [ES:EDI] 并更新 EDI。常用于初始化内存区域为同一值
LODS 串加载,从 [DS:ESI] 读入 AL/AX/EAX 并更新 ESI。较少使用,因为一次只加载一个值到累加器
CMPS 串比较,比较 [DS:ESI] 与 [ES:EDI] 并影响标志位。通常配合 REPE/REPNE 搜索匹配或不匹配的位置
SCAS 串扫描,比较 AL/AX/EAX 与 [ES:EDI] 并更新 EDI。常用于在内存中搜索特定值
REP 重复前缀,当 ECX ≠ 0 时重复执行后续串指令,每次执行后 ECX 自动减 1
REPE / REPZ 相等/为零时重复,ECX ≠ 0 且 ZF = 1 时继续(通常与 CMPS、SCAS 联用搜索匹配项)
REPNE / REPNZ 不等/不为零时重复,ECX ≠ 0 且 ZF = 0 时继续(用于搜索不匹配项)

方向标志 DF 控制串操作指针的移动方向:执行 CLD 后 DF=0,指针递增(正向处理);执行 STD 后 DF=1,指针递减(反向处理)。在使用串操作前应显式设置 DF,不要依赖默认值。


控制转移指令

控制转移指令改变程序执行流向,包括无条件跳转、条件跳转、循环以及过程调用与返回。

这是实现程序逻辑分支、循环和函数调用的基础。

无条件跳转与调用

无条件跳转不检查任何条件,直接改变 EIP/RIP 的值,让 CPU 从新地址继续执行。

助记符 功能简述
JMP 无条件跳转,支持短跳转(-128 到 +127 字节)、近跳转(段内)和远跳转(跨段)
CALL 调用过程,先将返回地址压入堆栈,然后跳转到目标地址
RET / RETF 从过程返回。RET 用于近返回(段内),RETF 用于远返回(跨段)。可带立即数参数同时释放栈上的参数空间

条件跳转

条件跳转根据标志寄存器中特定标志位的值决定是否跳转。

通常紧跟在 CMPTEST 指令之后使用。

助记符 跳转条件 典型用途
JE / JZ ZF = 1(相等 / 为零) CMP 后相等时跳转
JNE / JNZ ZF = 0(不等 / 不为零) CMP 后不等时跳转
JS SF = 1(结果为负) 运算结果为负数时跳转
JNS SF = 0(结果为正) 运算结果为非负数时跳转
JC CF = 1(有进位/借位) 无符号比较中小于时跳转,等同于 JB
JNC CF = 0(无进位/借位) 无符号比较中大于等于时跳转,等同于 JAE
JO OF = 1(有溢出) 有符号运算溢出时跳转
JNO OF = 0(无溢出) 有符号运算无溢出时跳转
JP / JPE PF = 1(低 8 位中 1 的个数为偶数) 奇偶校验为偶时跳转
JNP / JPO PF = 0(1 的个数为奇数) 奇偶校验为奇时跳转
JA / JNBE CF = 0 且 ZF = 0 无符号大于(Above)
JAE / JNB CF = 0 无符号大于等于(Above or Equal)
JB / JNAE CF = 1 无符号小于(Below)
JBE / JNA CF = 1 或 ZF = 1 无符号小于等于(Below or Equal)
JG / JNLE ZF = 0 且 SF = OF 有符号大于(Greater)
JGE / JNL SF = OF 有符号大于等于(Greater or Equal)
JL / JNGE SF ≠ OF 有符号小于(Less)
JLE / JNG ZF = 1 或 SF ≠ OF 有符号小于等于(Less or Equal)
JCXZ CX = 0 时跳转 16 位模式下判断 CX 是否为零
JECXZ ECX = 0 时跳转 32 位模式下判断 ECX 是否为零

无符号比较和有符号比较使用不同的跳转指令,这是初学者最容易出错的地方。例如,比较两个数时 JA 检查无符号大于,JG 检查有符号大于——同一个 CMP 结果在这两种判断下可能不同。

循环指令

循环指令使用 ECX 作为计数器,每次迭代自动递减并判断是否继续循环。

助记符 功能简述
LOOP ECX 减 1,若 ECX ≠ 0 则跳转到目标地址
LOOPE / LOOPZ ECX 减 1,若 ECX ≠ 0 且 ZF = 1 则跳转(等于时继续循环)
LOOPNE / LOOPNZ ECX 减 1,若 ECX ≠ 0 且 ZF = 0 则跳转(不等时继续循环)

中断与返回

助记符 功能简述
INT n 软件中断,调用中断向量号为 n 的中断服务程序(如 DOS 下 INT 21h 为系统功能调用)
INTO 溢出中断,当 OF = 1 时调用 INT 4(用于捕获算术溢出异常)
IRET / IRETD 从中断服务程序返回,恢复被中断时的 EFLAGS 和返回地址

条件设置指令

条件设置指令(386 及以上处理器支持)根据标志位状态将目的字节置为 1 或 0。

这类指令常用于消除分支跳转,提升代码执行效率——用条件设置替代短分支可以避免分支预测失败带来的性能损失。

助记符 设置条件 等价语义
SETZ / SETE ZF = 1 相等 / 结果为零时设置
SETNZ / SETNE ZF = 0 不等 / 结果不为零时设置
SETC CF = 1 有进位/借位时设置
SETNC CF = 0 无进位/借位时设置
SETO OF = 1 有溢出时设置
SETNO OF = 0 无溢出时设置
SETS SF = 1 结果为负时设置
SETNS SF = 0 结果为正时设置
SETG / SETNLE ZF=0 且 SF=OF 有符号大于时设置
SETGE / SETNL SF = OF 有符号大于等于时设置
SETL / SETNGE SF ≠ OF 有符号小于时设置
SETLE / SETNG ZF=1 或 SF≠OF 有符号小于等于时设置
SETA / SETNBE CF=0 且 ZF=0 无符号大于时设置
SETAE / SETNB CF = 0 无符号大于等于时设置
SETB / SETNAE CF = 1 无符号小于时设置
SETBE / SETNA CF=1 或 ZF=1 无符号小于等于时设置

CMP EAX, EBX 后跟 SETG AL 的效果是:如果 EAX 有符号大于 EBX,则 AL 被设为 1,否则为 0。这比 JG label; MOV AL, 1; JMP done; label: MOV AL, 0; done: 更简洁高效。


输入输出指令

I/O 指令用于 CPU 与外部设备端口之间的数据交换。

在 x86 架构中,端口地址空间与内存地址空间相互独立,需要通过专门的 I/O 指令来访问。

助记符 功能简述
IN 从指定端口读入数据到 AL/AX/EAX。端口地址在 0-255 时可直接写立即数,超过 255 时必须通过 DX 寄存器指定
OUT 将 AL/AX/EAX 中的数据写入指定端口。端口地址规则与 IN 相同
INS 从端口读入字节/字/双字到 ES:EDI 指向的内存,并自动更新 EDI(类似 STOS 但从 I/O 读取)
OUTS 将 DS:ESI 指向的内存字节/字/双字输出到端口,并自动更新 ESI

在现代操作系统中(Windows、Linux),用户态程序通常无法直接执行 I/O 指令——这些指令被操作系统限制为仅内核态可用。在 DOS 环境或裸机编程中则可以自由使用。


处理器控制与杂项指令

这类指令用于控制处理器的运行状态,包括标志位操作、同步控制和系统信息获取。

助记符 功能简述
CLC 清进位标志,CF 置为 0
STC 置进位标志,CF 置为 1
CMC 进位标志取反,CF 变为其相反值
CLD 清方向标志,DF 置为 0,串操作指针自动递增
STD 置方向标志,DF 置为 1,串操作指针自动递减
CLI 清中断标志,IF 置为 0,禁止可屏蔽硬件中断
STI 置中断标志,IF 置为 1,允许可屏蔽硬件中断
NOP 空操作,机器码为 0x90,不执行任何有效操作。常用于指令对齐、延时填充或预留补丁空间
HLT 停机,处理器暂停执行直到收到外部中断或复位信号
WAIT / FWAIT 等待 FPU 完成当前操作,主要用于与 x87 协处理器同步
LOCK 总线锁定前缀,使紧随其后的指令以原子方式执行。经典用法:LOCK XCHG 实现自旋锁、LOCK CMPXCHG 实现 CAS 操作
CPUID 获取 CPU 特征信息,包括厂商 ID、支持的指令集扩展等。调用前需在 EAX 中设置功能号
RDTSC 读取时间戳计数器,将 64 位计数值存入 EDX:EAX,用于高精度性能测量

浮点指令

以下为传统 x87 FPU 浮点指令,适用于使用浮点栈进行科学计算的场景。

在现代编程中,SSE/SSE2 等 SIMD 指令集已逐步取代 x87,但在理解遗留代码或进行简单浮点运算时,x87 仍被广泛使用。

助记符 功能简述
FLD 将浮点数从内存加载到 FPU 栈顶 ST(0),栈指针上移
FST / FSTP 将栈顶数据存入内存。FST 不弹出栈,FSTP 弹出栈(栈指针下移)
FADD 浮点加法,将 ST(0) 与指定操作数相加,结果存入 ST(0)
FSUB 浮点减法,ST(0) 减去指定操作数
FMUL 浮点乘法
FDIV 浮点除法,ST(0) 除以指定操作数
FCOM / FCOMP 比较 ST(0) 与指定操作数,设置 FPU 状态字中的条件码。FCOMP 比较后弹出栈
FCHS 改变 ST(0) 中数值的符号(正变负、负变正)
FSQRT 计算 ST(0) 的平方根,结果存入 ST(0)
FSIN / FCOS 计算 ST(0) 的正弦 / 余弦值(参数以弧度为单位),结果存入 ST(0)
FPTAN 计算 ST(0) 的正切值
FLD1 将常数 1.0 压入 FPU 栈顶
FLDZ 将常数 0.0 压入 FPU 栈顶
FLDPI 将常数 π(3.14159...)压入 FPU 栈顶

x87 FPU 使用浮点寄存器栈(ST(0) - ST(7) 共 8 个 80 位寄存器)进行操作。使用前需注意栈的深度限制——压入超过 8 个值会导致栈溢出异常。


注意事项

  • 区分有符号和无符号指令。MUL/IMUL、DIV/IDIV、条件跳转中的 JG/JA 系列对应不同的数值解释。汇编器不会帮你检查类型——用错指令会静默产生错误结果。

  • 串操作前务必设置 DF 标志。使用 CLD(递增)或 STD(递减)显式指定方向,不要假设默认值。不同编译器、不同调用约定的默认 DF 状态可能不同。

  • 现代操作系统限制特权指令。CLI/STI、HLT、IN/OUT 等指令在 Ring 3(用户态)下执行会导致异常。这些指令通常仅在操作系统内核或裸机环境中使用。

  • 优先使用现代指令集。在新代码中,条件设置指令(SETcc)优于条件跳转(消除分支预测开销),SSE/AVX 指令优于 x87(性能更好、编程模型更简单)。本表涵盖的 x87 和传统指令主要用于理解遗留代码。