目录
一、x86寄存器种类
AH | AL | AX | AX累加器 |
BH | BL | BX | BX基地址寄存器 |
CH | CL | CX | CX(循环)计数器 |
DH | DL | DX | DX数据寄存器 |
AX:常用于计算加减乘除时使用,作为乘除法的隐藏寄存器
BX:常用于基址变址寻址时作为基址寄存器
CX:在LOOP循环中用于存储循环次数
DX:用于保存16位乘法运算后的高16位和16位除法的余数
SI | 源变址寄存器 | 默认用于DS段,在字符串操作中指向源地址 |
DI | 目的变址寄存器 | 默认用于DS段,在字符串操作中指向目的地址 |
BP | 栈基址寄存器 | 默认用于SS段,指向当前函数的栈基地址 |
SP | 栈指针寄存器(栈顶指针) | 默认用于SS段,指向栈当前栈顶元素的地址 |
SI:默认作为DS段的偏移地址,可以段超越到CS、SS、ES作为变址寄存器
DI:默认作为DS段的偏移地址,可以段超越到CS、SS、ES作为变址寄存器
BP:默认作为SS段的基地址,可以段超越到CS、DS、ES作为基址寄存器
SP:只能作为SS段的栈顶指针寄存器,不可以段超越
DS | 数据段地址寄存器 | 指向当前程序的数据段地址 |
CS | 代码段地址寄存器 | 指向当前程序的代码段地址 |
SS | 栈段地址寄存器 | 指向当前程序的栈段地址 |
ES | 附加段地址寄存器 | 指向当前程序的附加(数据)段地址 |
DS:可以由MOV指令写入除了立即数和段地址寄存器以外的数据
CS:不可用MOV指令写入数据
SS:可以由MOV指令写入除了立即数和段地址寄存器以外的数据
ES:可以由MOV指令写入除了立即数和段地址寄存器以外的数据
ps:段地址寄存器均可用MOV指令将其中的值写入其他除了段地址的寄存器或主存储器中
二、x86汇编寻址方式
1.立即数寻址
MOV AX,1000H
MOV [1000H],1000H
2.寄存器寻址
MOV AX,BX
MOV [1000H],AX
3.直接寻址
[1000H]
DS:[1234H]
SS:[4321H]
4.寄存器间接寻址
[SI]
SS:[BX]
CS:[BP]
5.寄存器相对寻址
[BX+03H]
[SI+06H]
6.基址变址寻址
[BX+SI]
[BP+DI]
7.相对基址变址寻址
[BX+SI+06H]
[BP+DI+08H]
三、汇编常用指令
1.MOV指令
2.ADD指令
被加数只能是寄存器或者带有段地址和变量类型的主存储器,且两数不能同时为主存
当数据按无符号数求和后超过当前寄存器所能表示的最大值,则将CF标志位置1
当两个二进制最高位相同数的求和后高位发生变化,则将OF标志位置1
例如: XOR AX,AX ;清空AX寄存器
MOV AL,80H
ADD AL,80H
结果:AX=0000H CF=1,OF=1
3.SUB指令
被减数只能是寄存器或者带有段地址和变量类型的主存储器,且两数不能同时为主存
当数据按无符号数做差后小于0,将CF标志位置1
当两个二进制最高位不同数的求和后寄存器存储的数(被减数)高位发生变化,则将OF标志位置1
例如1: XOR AX;AX ;清空AX寄存器
MOV AL,80H
SUB AL,01H
结果: CF=0,OF=1
例如2: XOR AX;AX ;清空AX寄存器
MOV AL,01H
SUB AL,02H
结果: CF=1,OF=0
4.INC指令
被加数只能是寄存器或者带有段地址和变量类型的主存储器
INC指令不改变CF寄存器,只会与ADD一样改变其他寄存器
例如1: MOV AX,7FFFH
INC AX
结果:AX=8000H,CF=0,OF=1
例如2: MOV AX,0FFFFH
INC AX
结果:AX=0000H,CF=0,OF=0
5.DEC指令
被减数只能是寄存器或者带有段地址和变量类型的主存储器
DEC指令不改变CF寄存器,只会与SUB一样改变其他寄存器
例如1: MOV AX,0000H
DEC AX
结果:AX=FFFFH,CF=0,OF=0
例如2: MOV AX,8000H
DEC AX
结果:AX=7FFFH,CF=0,OF=1
6.NEG指令
反转数值的符号(由负变正,由正变负)
相当于用0减去操作数,标志位也相应变化
操作数为0时CF=0
操作数不为0时CF=1
操作数为-128(字节运算)或操作数为-32768(字运算)时OF=1
操作数不为-128(字节)或-32768(字)时OF=0
7.AND指令
将两个操作数进行与操作
不可以同时与两个主储存器内容
AND指令设置OF=CF=0,相应的改变SF,ZF,PF,不定义AF
8.OR指令
将两个操作数进行或操作
不可以同时或两个主储存器内容
OR指令设置OF=CF=0,相应的改变SF,ZF,PF,不定义AF
9.XOR指令
将两个操作数进行异或操作
不可以同时异或两个主储存器内容
XOR指令设置OF=CF=0,相应的改变SF,ZF,PF,不定义AF
10.NOT指令
将当前操作数按位取反
NOT指令不改变标志位
11.TEST指令
将两个操作数进行与运算,但不保存结果,只改变标志位
12.SHR指令
将操作数逻辑右移,最高位补0(数量只能使用1或cl)
按照移出的二进制位设置CF
当移动一位时,如果二进制最高位发生变化,则OF=1
当移动多位时,OF不确定
按照结果设置SF,ZF,PF对AF没有定义
13.SAR指令
将操作数算数右移,最高位进行符号位拓展(数量只能使用1或cl)
按照移出的二进制位设置CF
对OF无影响
按照结果设置SF,ZF,PF对AF没有定义
14.ROR指令
将操作数循环右移,最高位写入最低位的二进制值(数量只能使用1或cl)
按照移出的二进制位设置CF
对OF无影响
按照结果设置SF,ZF,PF对AF没有定义
15.RCR指令
将操作数循环右移,最高位写入CF寄存器值(数量只能使用1或cl)
按照移出的二进制位移入CF
对OF无影响
按照结果设置SF,ZF,PF对AF没有定义
16.CBW指令
将AL寄存器符号扩展到AX
17.CWD指令
将AX寄存器符号扩展到DX
18.FLAG CF操作指令
CLC | 令CF=0 |
STC | 令CF=1 |
CMC | 令CF取反 |
19.MUL指令
如果乘积结果的高位不是0,则CF=OF=1
否则为0
用来判断读取数据时是否要用高位寄存器
MUL AL,8位数 ;高位存在AH中 若AH=0则CF=OF=0
MUL AX,16位数 ;高位存在DX中 若DX=0则CF=OF=0
20.DIV指令
不影响标志位
DIV AL,8位数 ;余数存在AH中
DIV AX,16位数 ;余数存在DX中
四、流程控制
1.JCC指令
JZ/JE | ZF=1 | 运算结果等于零或cmp相等 |
JNZ/JNE | ZF=0 | 运算结果不等于零或cmp不相等 |
JS | SF=1 | 符号为负 |
JNS | SF=0 | 符号为正 |
JP/JPE | PF=1 | 二进制数中1的个数为偶数个 |
JNP/JPO | PF=0 | 二进制数中1的个数为奇数个 |
JO | OF=1 | 运算结果发生溢出 |
JNO | OF=0 | 运算结果没有溢出 |
JC/JB/JNAE | CF=1 | 运算结果进位/cmp低于/cmp不高于等于(适用于无符号数) |
JNC/JNB/JAE | CF=0 | 运算结果没有进位/cmp不低于/cmp高于等于(适用于无符号数) |
JBE/JNA | CF=1或ZF=1 | cmp结果低于等于/cmp结果不高于(适用于无符号数) |
JNBE/JA | CF=0且ZF=0 | cmp结果不低于等于/cmp结果高于(适用于无符号数) |
JL/JNGE | SF!=OF | cmp结果小于/cmp结果不大于等于(适用于有符号数) |
JNL/JGE | SF=OF | cmp结果不小于/cmp结果大于等于(适用于有符号数) |
JLE/JNG | SF!=OF或ZF=1 | cmp结果小于等于/cmp结果不大于(适用于有符号数) |
JNLE/JG | SF=OF且ZF=0 | cmp结果不小于等于/cmp结果大于(适用于有符号数) |
2.LOOPZ/LOOPE指令
循环条件:CX!=0,ZF=1
3.JCXZ指令
跳转条件:CX=0
4.LOOPNZ/LOOPNE指令
循环条件:CX!=0,ZF=0
5.RET指令
RET指令后可携带一个16位的立即数,将在移除IP和CS指针后再将SP加上这个立即数来废除调用函数时传进来的参数
五、x86汇编语言程序格式
1.数据定义伪指令dup()
dataname db 10 dup('A') ;在连续空间内定义十个'A'
dataname db 10 dup('abc') ;在连续空间内定义十个'abc'
dataname db 10 dup(?) ;申请十个未赋值空间
2.定位伪指令$
$表示当前偏移地址值
dataname db 10 dup('A')
length equ $-dataname ;length表示dataname的字节数
3.常量定义伪指令EQU(=)
constname equ 100 ;定义常量constname的值为100
constname = 100 ;定义常量constname的值为100
constname equ <MOV AX,0> ;constname可以被替换为<>内的语句
4.类型指定伪指令THIS
data_byte equ THIS byte ;按照字节的方式访问data_word,与其有相同首地址
;data_byte LABEL byte LABEL等价于EQU THIS
data_word dw 1234H
5.高低分离符
HIGH | 分离出16位立即数或常量的高8位 | MOV AL,HIGH 8060H | AL=80H |
LOW | 分离出16位立即数或常量的低8位 | MOV AL,LOW 8060H | AL=60H |
HIGHWORD | 分离出32位立即数或常量的高16位 | MOV AX,HIGHWORD 12345678H | AX=1234H |
LOWWORD | 分离出32位立即数或常量的低16位 | MOV AX,LOWWORD 12345678H | AX=5678H |
6.变量(标号)类型伪指令TYPE
例如1:
dataname db 12H
MOV AX,TYPE dataname ;对应db、dw、dd依次返回1、2、4
例如2:
MOV AX,TYPE LABEL ;对应短、近、远转移依次返回FF01H、FF02H、FF05H
LABEL: INC AX
7.变量字节数伪指令SIZEOF
返回该变量所占用的字节数目
dataname dw 10 dup('A')
MOV AX,SIZEOF dataname ;AX=20
8.变量长度伪指令LENGTHOF
返回该变量的元素个数
SIZEOF=LENGTHOF✖️TYPE
dataname dw 10 dup('A')
MOV AX,LENGTHOF dataname ;AX=10
9.类型名伪指令PTR
BYTE | BYTE PTR[] | 指定类型为字节 |
WORD | WORD PTR[] | 指定类型为字 |
DWORD | DWORD PTR[] | 指定类型为双字 |
NEAR | NEAR PTR LABEL | 指定为近转移 |
FAR | FAR PTR LABEL | 指定为远转移 |
六、x86汇编语言程序设计
1.地址表的构建
.data
table dw disp1,disp2,disp3 ;构建不同代码段对应的地址表
.code
start: MOV AX,@data
MOV DS,AX
JMP table[1]
disp1: ;代码段1
disp2: ;代码段2
disp3: ;代码段3
2.从键盘输入一个字符
MOV AH,1 ;设置调用系统函数为:从键盘输入一个字符
INT 21H ;调用系统中断
MOV BL,AL ;读入的字符ASCII码保存在AL中,转移到BL,准备接收新的字符
3.输出一个字符到显示器
MOV AH,2 ;设置调用系统函数为:输出一个字符到显示器
MOV DL,'A' ;DL中保存要输出字符的ASCII码
INT 21H ;调用系统中断
七、x86汇编语言宏定义
宏内注释用两个;
1.不带参数的宏
mainbegin MACRO ;;定义一个名字为mainbegin的宏
MOV AX,@data
MOV DS,AX
ENDM
2.带参数的宏
宏的参数既可以指代常数,也可指代寄存器,还可以指代指令名
shlext MACRO shloprand,shlnum ;;定义两个参数,分别用来指代寄存器和常数
PUSH CX
MOV CL,shlnum
SHL shloprand,CL
POP CX
ENDM
3.宏操作符
①&操作符
当参数紧跟在其他字符前或后时,或者出现在带有引号的字符串内时,用&限定表示为参数
shift MACRO soprand,snum,sopcode
PUSH CX
MOV CL,snum
s&sopcode& soprand,CL
POP CX
ENDM
shift ax,8,hl ;表示将ax逻辑左移8位
shift ax,8,ar ;表示将ax算数右移8位
②<>操作符
如果传递的参数中含有逗号、空格等间隔符号,要用<>加以限制,来保证字符串的完整
datadef MACRO name,number
name db number
ENDM
datadef num1,1,2,3 ;展开为:num1 db 1
datadef num1,<1,2,3> ;展开为:num1 db 1,2,3
③!操作符
!用于指示其后一个字符失去其操作符身份,作为普通字符
④%操作符
用于表示其后紧接的一个表达式计算结果的值作为实参,而不是传入表达式本身
pushdata MACRO thesegment,param
PUSH word ptr thesegment:[param*2]
ENDM
pushdata ds,100+5 ;宏展开为:PUSH word ptr ds:[100+5*2]
pushdata ds,%100+5 ;宏展开为:PUSH word ptr ds:[105*2]