因为网上各种各样的笔记都不如自己写一遍来得方便查阅,所以按照自己的喜好整理一下汇编的笔记。目前跟着Kip Irvine的书才学到第六章(条件跳转),所以再之后的笔记暂时保留,等之后学完了再整理吧。
部分表格来源于:
https://blog.csdn.net/qq_36982160/article/details/82950848
插图ID:87882344
常用的寄存器:
31----------16 | 15---8 | 7----0 | 16位 | 32位 |
AH | AL | AX | EAX | |
BH | BL | BX | EBX | |
CH | CL | CX | ECX | |
DH | DL | DX | EDX | |
BP | EBP | |||
SI | ESI | |||
DI | EDI | |||
SP | ESP |
注:在VisualStudio还能看见EFL与EIP两种寄存器
EAX:拓展累加器。常用于做累加器、取返回值等操作。
EBX:基底暂存器。
ECX:计数暂存器。
EDX:资料暂存器。
ESI:拓展源变址寄存器。
EDI:拓展目的变址寄存器。
ESP:拓展帧指针寄存器,也叫栈指针寄存器(extended stack pointer),存放着一个指针,该指针永远指向系统栈最上面一个栈帧的栈顶(我将其当作一个指向当前调用处的栈指针)
EBP:基址指针寄存器(extended base pointer),存放着一个指针,该指针永远指向系统栈最上面一个栈帧的底部(我将其当作一个指向当前过程的起始栈址的栈指针)
EFL:EFLAGS寄存器。包含了独立的二进制位(状态标志位),用于控制CPU操作或反应CPU的结果。
EIP:指令指针。存放下一条将要指向的指令的地址。
状态标志位:
CF进位标志位 | 主要反映算术运算是否产生进位或借位,若产生,则CF=1,否则CF=0 |
OF溢出标志位 | 反映有符号数运算结果是否产生溢出,是置1,否置0 |
SF符号标志位 | 根据运算结果的最高位,若最高位为1则SF为1,否则为0,反映了有符号数运算结果的正负(0正1负) |
ZF零标志位 | 反映运算结果是否为0 |
AC辅助进位标志位 | AF=1时,向高位或高字节进位或借位 |
PF奇偶校验标志位 | 运算结果操作数位为1的个数为偶数个时为1,否则为0. |

对应EFL寄存器中的顺序。
不过,有的集成开发环境里对状态标志位的写法是不一样的,下图为为别名(其实也不能称为别名,但姑且这么形容比较方便吧)。

状态标志操作指令
指令 | 中文名 | 格式 | 解释 |
---|---|---|---|
CLC(clear carry flag) | 清进位标志指令 | CLC | 使进位标志CF为0 |
STC(set carry flag) | 置进位标志指令 | STC | 使进位标志CF为1 |
CMC(complement carry flag) | 进位标志取反指令 | CMC | 使进位标志CF取反 |
LAHF(load status flags into AH register) | 获取状态标志操作指令 | LAHF | 把位于标志寄存器低端的5个状态标志位(p26图2.3)信息同时送到寄存器AH的对应位 |
SAHF(store AH into Flags) | 设置状态标志操作指令 | SAHF | 对标志寄存器中的低8位产生影响,使得状态标志位SF、ZF、AF、PF和CF分别成为来自寄存器AH中对应位的值,但保留位(位1、位3、位5)不受影响 |
数据类型:
类型 | 用法 |
BYTE | 8位无符号整数,B代表字节 |
SBYTE | 8位有符号整数,S代表有符号 |
WORD | 16位无符号整数 |
SWORD | 16位有符号整数 |
DWORD | 32位无符号整数,D代表双(字) |
SDWORD | 32位有符号整数 |
FWORD | 48位整数(保护模式下的远指针) |
QWORD | 64位整数,Q代表四(字) |
TBYTE | 80位整数,T代表10字节 |
REAL4 | 32位IEEE短实数(4字节) |
REAL8 | 64位IEEE长实数(8字节) |
REAL10 | 80位IEEE拓展实数(10字节) |
伪指令:
指令 | 作用 |
“=” | 可将立即数与标记划等号,在调用标记时将直接进行替代 |
“$” | 当前地址计数器。直接代表了当前位置的地址偏移量 |
DUP | 可直接为数据分配空间。例:BYTE 20 DUP(0) 分配20字节 |
EQU | 将符号名称与整数表达式或任意文本相连(类似于"=",但更偏向于定义赋值,区别在于不可重定义) |
TEXTEQU | 创建文本宏。<text>分配文本/textmacro分别文本宏内容/%constExpr分配整数常量 |
简单传送指令
指令 | 中文名 | 格式 | 解释 | 备注 |
---|---|---|---|---|
MOV | 传送指令 | MOV DEST,SRC | DEST<=SRC | |
XCHG | 交换指令 | XCHG OPER1,OPER2 | 把操作数oper1的内容与操作数oper2的内容交换 | oper1和oper2可以是通用寄存器或存储单元,但不能同时是操作单元,也不能是立即数。 |
拓展传送指令
指令 | 中文名 | 格式 | 解释 | 备注 |
---|---|---|---|---|
MOVSX | 符号拓展传送指令 | MOVSX DEST,SRC | 把源操作数SRC符号拓展后送至目的操作数DEST | src可以是通用寄存器或者存储单元,但是dest只能是通用寄存器(零拓展传送指令不会改变源操作数,也不影响标志寄存器的状态) |
MOVZX | MOVZX DEST,SRC | 把源操作数SRC零拓展后送至目的操作数DEST | 零拓展传送指令不会改变源操作数,也不影响标志寄存器的状态 |
简单加减指令
指令 | 中文名 | 格式 | 解释 | 备注 |
---|---|---|---|---|
ADD | 加法指令 | ADD DEST,SRC | DEST<=DEST SRC | 两数相加,结果于前 |
SUB | 减法指令 | SUB DEST,SRC | DEST<=DEST-SRC | 两数相减,结果于前 |
INC | 加1指令 | INC DEST | DEST<=DEST 1 | |
DEC | 减1指令 | DEC DEST | DEST<=DEST-1 | |
NEG | 取补指令 | NEG OPRD | OPRD=0-OPRD | 对操作数取补(相反数) |
常用条件转移指令
指令 | 中文名 | 格式 | 解释 | 备注 |
---|---|---|---|---|
CMP | 比较指令 | CMP DEST,SRC | 根据dest-src的差影响各状态标志寄存器 | 不把dest-src的结果送入dest |
JMP | 无条件段内直接转移指令 | JMP LABEL | 使控制无条件地转移到标号为label的位置 | 无条件转移指令本身不影响标志 |

堆栈和堆栈操作
指令 | 中文名 | 格式 | 解释 | 备注 |
---|---|---|---|---|
PUSH | 进栈指令 | PUSH SRC | 把源操作数src压入堆栈 | 源操作数src可以是32位通用寄存器、16位通用寄存器和段寄存器,也可以是双字存储单元或者字符存储单元,还可以是立即数 |
POP | 出栈指令 | POP DEST | 从栈顶弹出一个双字或字数据到目的操作数 | 如果目的操作数是双字的,那么就从栈顶弹出一个双字数据,否则,从栈顶弹出一个字数据,出栈至少弹出一个字(16位)该指令弹出ESP处数据 |
PUSHA | 16位通用寄存器全进栈指令 | PUSHA | 将所有8个16位通用寄存器的内容压入堆栈 | 压入顺序是AX CX DX BX SP BP SI DI,然后对战指针寄存器SP的值减16,所以SP进栈的内容是PUSHA指令执行之前的值 |
POPA | 16位通用寄存器全出栈指令 | POPA | 以PUSHA相反的顺序从堆栈中弹出内容,从而恢复PUSHA之前的寄存器状态 | SP的值不是由堆栈弹出的,而是通过增加16来恢复 |
PUSHAD | 32位通用寄存器全进栈指令 | PUSHAD | 将所有8个32位通用寄存器的内容压入堆栈 | 压入顺序是EAX ECX EDX EBX ESP EBP ESI EDI,然后对栈指针寄存器ESP的值减32,所以SP进栈的内容是PUSHAD指令执行之前的值 |
POPAD | 32位通用寄存器全出栈指令 | POPAD | 以PUSHAD相反的顺序从堆栈中弹出内容,从而恢复PUSHAD之前的寄存器状态 | ESP的值不是由堆栈弹出的,而是通过增加32来恢复 |
过程调用和返回指令
指令 | 中文名 | 格式 | 解释 | 备注 |
---|---|---|---|---|
CALL | 过程调用指令 | CALL LABEL | 段内直接调用LABEL | 与jmp的区别在于call指令会在调用label之前保存返回地址(call 中return之后主程序还可以继续执行,jmp 当label执行完毕后不能返回主程序继续执行) |
RET | 段内过程返回指令 | RET | 使子程序结束,继续执行主程序 | ret 4;ret 8等分别标识返回后回退的栈帧大小 |
逻辑运算指令
指令 | 中文名 | 格式 | 解释 | 备注 |
---|---|---|---|---|
NOT | 否运算指令 | NOT OPRD | 把操作数OPRD按位取反,然后送回OPRD | |
AND | 与运算指令 | AND DEST,SRC | 把两个操作数进行与运算之后结果送回DEST | 同1得1,否则得0 |
OR | 或运算指令 | OR DEST,SRC | 把两个操作数进行或运算之后结果送回DEST | 同0得0,否则得1 |
XOR | 异或运算 | XOR DEST,SRC | 把两个操作数进行异或运算之后结果送回DEST | 相同得0不同得1 |
TEST | 测试指令 | TEST DEST,SRC | 与AND指令类似,将各位相与,但是结果不送回DEST,仅影响状态位标志,指令执行后,ZF、PF、SF反映运算结果,CF和OF被清零 | 通常用于检测某些位是否为1,但又不希望改变操作数的值 |
循环指令
指令 | 中文名 | 格式 | 解释 | 备注 |
---|---|---|---|---|
LOOP | 计数循环指令 | LOOP LABEL | 使ECX的值减1,当ECX的值不为0的时候跳转至LABEL,否则执行LOOP之后的语句 | |
LOOPE | 等于循环指令 | LOOPE LABEL | 使ECX的值减1,如果结果不等于0并且零标志ZF等于1(表示相等),那么就转移到LABEL,否则执行LOOPE之后的语句 | |
LOOPZ | 零循环指令 | LOOPZ LABEL | 使ECX的值减1,如果结果不等于0并且零标志ZF等于1(表示相等),那么就转移到LABEL,否则执行LOOPZ之后的语句 | |
LOOPNE | 不等于循环指令 | LOOPE LABEL | 使ECX的值减1,如果结果不等于0并且零标志ZF等于0(表示不相等),那么就转移到LABEL,否则执行LOOPNE之后的语句 | |
LOOPNZ | 非零循环指令 | LOOPNZ LABEL | 使ECX的值减1,如果结果不等于0并且零标志ZF等于0(表示不相等),那么9就转移到LABEL,否则执行LOOPNZ之后的语句 | |
JECXZ | 计数转移指令 | JECXZ LABEL | 当寄存器ECX的值为0时转移到LABEL,否则顺序执行 | 通常在循环开始之前使用该指令,所以循环次数为0时,就可以跳过循环体 |
LEA:将存储器操作数mem的4位16进制偏移地址送到指定的寄存器。
LEA reg16,mem
ENTER/LEAVE:自动创建栈帧/自动删除栈帧
MySub PROC
ENTER 8,0
.
.
.
LEAVE
RET
MySub ENDP
;上下两端代码有着相同的意义 编译器将把上面的代码翻译为下面的代码
MySub PROC
push ebp
mov ebp,esp
sub esp,8
.
.
.
mov esp,ebp
pop ebp
ret
MySub ENDP
REP:重复指令。以ECX为计数器。
rep movs dword ptr es:[edi],dword ptr ds:[esi]
意思bai就是将ESI指向的du地址zhi的值以4字节方式拷贝到daoEDI指向的地址中,重复执行ECX次,每次执zhuan行后ESI+4,EDI+4,ECX-1,OD中在这段代码中下断后按F7单步步入就可以观察到这3个寄存器的变化
STOS:是将AL/AX/EAX的值存储到[EDI]指定的内存单元中
STOS BYTE PTR ES:[EDI] ——BYTE:把al的值放到EDI指定的位置
STOS WORD PTR ES:[EDI] ——WORD:把ax的值放到EDI的指定位置
STOS DWORD PTR ES:[EDI] ——DWORD:把EAX的值放到EDI的位置
INVOKE:只用于32位模式,用于将参数入栈(INVOKE procedureName [, arguementList])后者代表入栈的数据,可为列表
PROC:(label PROC [attributes] [USES reglist] ,paramenter_list)
PROTO:64位中用于指定程序的外部过程/32位中可包含参数
如上三者分别可在32位模式下表示:(过程调用——过程实现——过程原型)
汇编语言的常用编辑格式:
.386;表示为32位程序
.model flat,stdcall;储存形式 声明(内存模式/调用规范)
.stack 4096; 表示分配4096字节空间用于堆栈
ExitProcess PROTO,dwExitCode:DWORD
INCLUDE Irvine32.inc;调用链接库
;分号在汇编中为注释符
.data ;可在下方申请变量
VALL BYTE 20h,30h,40h,50h;数组声明
greet BYTE "hello world",0
BYTE "i want to creat a program",0dh,0ah
byte "so i try to exit this greet ",0dh,0ah,0
;字符串声明
.data? ;同样是声明变量的区域
.code ;程序代码区起始点 标记
main PROC ;程序入口
mov eax,0
mov ebx,5
mov ecx,7
call SumOf
INVOKE ExitProcess,0
main ENDP ;过程的结束
SumOf PROC ;类似于函数,通过call指令调用
add eax,ebx
add eax,ecx
ret
SumOf ENDP
END main ;程序的结束
Comments | NOTHING