一.寻址方式
立即寻址:
MOV AX,1234H
MOV AL,5
MOV BX,3064H
寄存器寻址:
可为AX/BX/CX/DX/SI/DI/SP/BP/AL/AH/BL/BH/CL/CH/DL/DH
MOV AX,BX
直接寻址:
有效地址即偏移地址
MOV AX,[8054] 默认DS 段前缀
可用符号地址代替数值地址
注意:MOV AX,VALUE等价于MOV AX,[VALUE]
寄存器间接寻址:
操作数有效地址在SI DI BP BX
SI/DI/BX默认是DS(数据段)
BX默认是SS
MOV AX,[SI]
可用段前缀 MOV AX.ES:[BX]
寄存器相对寻址:
操作数的有效地址是一个基址寄存器(BX,BP)或变址寄存器(SI,DI)的内容加上指令中给定的8位或16位位移量之和
PA = DS*16+BX/SI/DI+位移量
PA = SS*16+BP+位移量
MOV AX,[DI+1223H]
MOV AX,[SI+3]等价于MOV AX,3[SI]
基址加变址:
操作数有效地址由基址寄存器之一的内容+变址寄存器之一的内容
MOV AX,[BX][DI]等价于MOV AX,[BX+DI]
适合表格或数组处理
相对基址加变址:
操作数有效地址由基址寄存器之一的内容+变址寄存器之一的内容+指令给定的8位或16位位移量
指令中给定8位或16位位移量采用补码表示
如果位移量是8位,那么被带符号扩展成16位
如果超过FFFFH时就取其64K的模
MOV AX,[BX+DI+1234H]等价于MOV AX,1234H[BX+DI]等价于MOV AX,1234H[BX][DI]
二.指令语句
[标号:] 指令助记符 [操作数] [;注释]
三.指令功能
1.数据传送指令:
又分传送指令和交换指令
(1)传送指令:
MOV DST,SRC
(a)CPU寄存器之间的数据传送
注意:源和目的操作数不能同时是段寄存器,代码段CS不能作为目的操作数
指令指针IP既不能作为源,也不能作为目的
(b)立即数送至通用寄存器或存储单元
注意:立即数不能直接传送到段寄存器,立即数不能作为目的操作数
(c)寄存器与存储器间的数据传送
注意:
源操作数和目的操作数类型要一致,8位与16位不能互传
两个操作数必须有一个寄存器(除了立即寻址),不能同时为存储器
如果要在两个存储单元间传送数据,可利用通用寄存器过渡的方法进行,如:
MOV AX,VARW1
MOV VARW2,AX
若MOV VARW2,VARW1 ;错误
这种方法也适用于段寄存器间的数据传送。
MOV BX,OFFSET TABLE ;把TABLE的偏移地址(不是内容)送到BX寄存器中,
OFFSET是属性操作符。
MOV指令不影响标志位。
(2)交换指令
XCHG OPRD1,OPRD2
OPRD1,OPRD2不能是段寄存器,不能是立即数,也不能同时是存储单元。
同时是字节或者同时都是字。
不影响标志位。
(3)地址传送指令
8086/8088有三条地址传送指令
(a)指令LEA : 传送有效地址指令
LEA REG,OPRD ;该指令把操作数OPRD的有效地址(偏移地址)传送到操作数REG
操作数OPRD必须是一个存储器操作数,操作数REG必须是一个16位的通用寄存器
与OFFSET区别,OFFSET是编译器 LEA是执行期
(b)LDS 段值和段内偏移构成32位的地址指针,该指令传送32位地址指针
LDS REG,OPRD
执行的操作:(REG)<-- (SRC)
(DS) <--(SRC+2)
该指令把操作数OPRD中所含的一个32位地址指针的段值部分送到数据段寄存器DS,
把偏移部分送到指令给出的通用寄存器REG。
OPRD必须是一个32位的存储器操作数,REG可以是16位通用寄存器,但实际使用
往往是变址寄存器或指针寄存器。
例子:
LDS SI,[10H] 指令执行前(DS)= C000H,(C0010H)=0180,(C0012H) = 2000H
指令执行后(SI) = 0180H,(DS) = 2000H
(c)LES
同LDS区别:将段值送到附加寄存器ES。
(4)堆栈操作指令
堆栈是一段RAM区域。称为栈底的一端地址较大(高地址),称为栈顶的一端地址较小(低地址)。
堆栈指针寄存器SP始终指向栈顶。
堆栈指令分两种:
(a)进栈指令PUSH
PUSH SRC
执行的操作:SP<--(SP)-2
该指令把源操作数SRC压入堆栈,它先把堆栈指针寄存器SP的值减2,
然后再把源操作数SRC送入SP指向的栈顶。
SRC可以是通用寄存器和段寄存器,也可以是字存储单元。
(b)出栈指令 POP
POP DST
(SP)<--(SP)+2
该指令从栈顶弹出一个字数据到目的操作数DST,然后SP+2
DST可以是通用寄存器和段寄存器(除CS),也可以是字存储单元,但不能是立即数。
注意,PUSH POP只能是字操作。此两条指令都不影响标志位。
例:假设(SS)=2250,(SP)=0140,在堆栈中存入五个数据,那么栈顶的无聊地址是多少?
未存入数据之前物理地址:22500+0140=22640H
存入5个数据后:22640-0A=22636H
注意这里5个数据占10个字节(5个字),因此减去0A。
(5)标志操作指令:
(a)标志传送指令:
指令LAHF
该指令把标志寄存器的低8位(包括SF,ZF,AF,PF,CF)传送到寄存器AH的指定位。
指令SAHF
与LAHF相反,将AH的指定位送至标志寄存器的低8位的SF,ZF,AF,PF,CF
OF DF IF TF SF ZF AF PF CF
11 10 9 8 7 6 4 2 0
指令PUSHF
把标志寄存器的内容压入堆栈
指令POPF
把当前堆栈顶的一个字传送到标志寄存器。
(b)标志位操作指令
仅对指令规定的标志产生影响,对其他标志没有影响
(1)清进位标志指令CLC
(2)置进位标志指令STC
(3)进位标志取反指令CMC
(4)清方向标志CLD
(5)置方向标志STD
(6)清中断允许标志CLI
(7)置中断允许标志STI
2.加减运算指令
(1)加法指令 ADD
ADD OPRD1,OPRD2
(OPRD1)<--(OPRD1)+(OPRD2)
注意:
OF位根据操作数的符合及其变化情况来设置:若两个操作数的符号相同而结果
的符号与之相反时OF=1,否则OF=0
CF位可以用来表示无符号数的溢出。由于无符号数的最高有效位为数值位非符号位。
所以从该位产生的进位应该是结果的实际进位。
ADD指令影响标志位。
(2)带进位加指令 ADC
ADC OPRD1,OPRD2
OPRD1<--OPRD1+OPRD2+CF
实现双精度数加法,必须使用两条指令。
使用ADC指令以便把前一条ADD指令作低位字加法所产生的进位值加入高位字之内。
另外,带符号的双精度数的溢出,应该根据ADC指令的OF位来判断,而作低位加法
用的ADD指令的溢出是无意义的。
(3)加1指令INC
INC OPRD
影响ZF,SF,OF,PF,AF,不影响CF
主要用于调整地址指针和计数器。
例子:写出把首地址为BLOCK的字数组的第6个字送到DX寄存器的指令
(1)寄存器间接寻址:
MOV BX,OFFSET BLOCK ;或LEA BX,BLOCK
ADD BX,000AH
MOV DX,[BX]
(2)寄存器相对寻址:
MOV BX,OFFSET BLOCK
MOV DX,[BX+000AH]
(4)减法指令SUB
SUB OPRD1,OPRD2
(OPRD1)<---(OPRD1)-(OPRD2)
CF OF类似于加法指令
(5)带借位的减法SBB
SBB OPRD1,OPRD2
(OPRD1)<---(OPRD1)-(OPRD2)-CF
(6)减1指令DEC
DEC OPRD
同INC,不影响CF
主要用于调整地址指针和计数器。
(7)取补指令NEG
NEG OPRD ;用零减去操作数OPRD,再把结果送回OPRD
对-128取补,或在字操作时对-32768取补,则操作数不变,但OF被置为1,其他情况均为0.
对0求补,CF=0,其他情况为1。
(8)比较指令CMP
CMP OPRD1,OPRD2
OPRD1,OPRD2不能同时为存储单元。
比较结果不送到OPRD1,但影响标志CF,ZF,SF,OF,AF和PF
执行了比较指令后,如果ZF为1,则两者相等
如果两者是无符号数,则可根据CF判断大小
如果两者是有符号数,则要根据SF和OF判断大小
例子:
设X,Y,Z均为双精度数,他们分别存放在地址为X,X+2,Y,Y+2,Z,Z+2的存储单元中,存放时高位字节
在高地址中,低位字在低地址中。用指令实现 W<--X+Y+24-Z
MOV AX,X
MOV DX,X+2
ADD AX,Y
ADC DX,Y+2
ADD AX,24
ADC DX,0
SUB AX,Z
SBB DX,Z+2
MOV W,AX
MOV W+2,DX
例子:写出对存放在DX和AX中的双字长数求补的指令序列
NEG DX ;必须先对高位求补
NEG AX
SBB DX,0
例子:指出下列指令的错误:
a.MOV AX,[SI][DI]
b.CMP 15,BX
c.PUSH BL
d.POP CS
e.CMP OP1,OP2(OP1,OP2都为字节变量)
f.CMP AX,OP1
答:
a.必须一个为基址一个为变址
b.立即数不能作为目的数
c.堆栈操作指令都以字为单位,必须是字操作
d.代码段不能做目的操作数
e.两个操作数不能都为存储单元
f.一个为字一个为字节
3.乘除运算指令
乘除运算指令分为无符号数运算和有符号数运算指令
对标志位影响有些特别
(1)乘法指令
一个操作数总是隐含在寄存器AL(8位相乘)或AX(16位相乘)中,
另一个操作数可以采用除立即数以外的任一种寻址方式。
在乘法指令中,目的操作数必须是累加器
(a)无符号数乘法指令
MUL OPRD
两个8位数的16位乘积存放在AX中,两个16位数的32位乘积存放在DX、AX中,
DX存放高位字,AX存放低位字。
如果乘积结果的高半部分不等于零,则CF=1,OF=1.否则都为0.
该指令对其他标志位无定义。
(b)有符号数乘法指令 IMUL
IMUL OPRD
如果乘积结果的高半部分不是低半部分的符号扩展,则标志CF=1,OF=1;否则都为0
(2)除法指令
一个操作数总是隐含在寄存器AL(除数是8位)或AX(除数是16位)中,
另一个操作数可以采用除立即数以外的任一种寻址方式。
字节操作(AX/OPRD(8位))商放在AL中,余数放在AH中
字操作((DX,AX)/OPRD(16位))商放在AX中,余数放在DX中
(a)无符号数除法指令DIV
DIV OPRD
如果除数为0,或者在8位数除时商超过8位,或者在16位除时商超过16位。则认为是除溢出。
引起0号中断。
除法对标志位的影响无定义。
(b)有符号数除法指令IDIV
当除数为0,或者商太大(字节时超过127,字除时超过32767),或者商太小(字节时小于-127,
字除时小于-32767),引起0号中断。
(3)符号扩展指令
(a)字节转换为字指令CBW(CONVERT BYTE TO WORD)
格式: CBW ;把寄存器AL中的符号扩展到寄存器AH
例子: MOV AX,3487H ;AX = 3487H,AH = 34H,AL = 87H
CBW ;AL=10000111 AH-->1111111110000111
该指令不影响各标志位。
(b)字转换为双字指令CWD(CONVERT WORD TO DOUBLE)
CWD ;把寄存器AX中的符号位扩展到寄存器DX
不影响各标志位
例子:计算如下表达式的值:(X*Y+Z-1024)/75
假设其中的X,Y,Z均为16位带符号数,分别存放在名为XXX,YYY和ZZZ的变量单元中
再假设计算结果的商保存在AX中,余数保存在DX中。
MOV AX,XXX
IMUL YYY
MOV CX,AX ;低8位保存在CX
MOV BX,DX ;高8位保存在BX
MOV AX,ZZZ
CWD ;把ZZZ扩展为32位
ADD AX,CX
ADC DX,BX
SUB AX,1024 ;立即数无需位扩展
SBB DX,0
MOV CX,75
IDIV CX
4.逻辑运算和移位指令
(1)逻辑运算指令
(a)否操作指令NOT
NOT OPRD
这条指令把操作数OPRD取反,然后送回OPRD
OPRD不能为立即数
对标志位无影响
(b)与操作数AND
AND OPRD1,OPRD2 ;该指令对两个操作数进行按位的逻辑与运算,结果送到目的操作数OPRD1
该指令执行后,标志CF=0,OF=0.标志PF,ZF,SF反映运算结
果,AF未定义
某个操作数与自己相与,则值不变,但CF清0
(c)或操作指令OR
OR OPRD1,OPRD2
该指令执行后,标志CF=0,OF=0.标志PF,ZF,SF反映运算结
果,AF未定义
某个操作数与自己相或,则值不变,但CF清0
(d)异或操作指令
该指令执行后,标志CF=0,OF=0.标志PF,ZF,SF反映运算结
果,AF未定义
某个操作数与自己相异或,则结果为0,并可使CF清0
(e)测试指令TEST
TEST OPRD1,OPRD2
与AND类似,但是结果不回送。
该指令执行后,标志CF=0,OF=0.标志PF,ZF,SF反映运算结
果,AF未定义
通常用于检测某些位是否为1,但又不希望改变原来的操作数。
例:要检查AL中的位6或位2是否有一位为1:
TEST AL,01000100B ;符号B表示二进制
如果位6和位2全为0,那么执行上面指令后ZF被置为1.否则ZF被清0。
(2)一般移位指令
(a)算术左移或逻辑左移指令SAL/SHL
算术左移和逻辑左移进行相同的动作,虽然有两个助记符,但是只有一条机器指令。
SAL OPRD,m ;一般用于有符号数
SHL OPRD,m ;一般用于无符号数
执行的操作相同,将操作数OPRD左移m,每移动一位一位,右边补足0
移出的最高位进入标志位CF
MOV AL,8CH
SHL AL,1 ;A=18H,CF=1,PF=1,ZF=0,SF=0,OF=0
MOV CL,6 ; CL=6
SHL AL,CL ;AL=0,CF=0,PF=1,ZF=1,SF=0,OF=0
注意,如果m大于1,则必须先将m存入CL中。
溢出标志位OF只有当m=1时菜有效,如果m>1则OF无效,始终为0。
每左移一次相当于元素乘2(如果未溢出)。
例子:
实现把寄存器AL中的内容(设为无符号数)乘10,结果存放在AX中
XOR AH,AH ;(AH)=0 先将AH清零
SHL AL,1 ;2X
MOV BX,AX ;暂存2X
SHL AX,1 ;4X
SHL AX,1 ;8X
ADD AX,BX ;8X+2X
(b)算术右移指令SAR
SAR OPRD,m
该指令使操作数右移m位,每移一位,注意:左边符号位不变,移出的最低位
进入标志位CF。
m>1时,必须先把m存到CL
MOV CL,5
SAR [DI],CL
(c)逻辑右移指令SHR
SHR OPRD,m
右移m位,左边用0补足。移出最低位进入标志位CF
例子:假设DATA1和DATA2各长4位,分别存放于AL寄存器的低4位和高4位中,现在要把他们分别
存放在BL寄存器和BH寄存器的低4位中
MOV BL,AL
AND BL,OFH ;得DATA1
MOV BH,AL
MOV CL,4
SHR BU,CL
(3)循环移位指令
这些指令可一次只移一位,也可以一次移多位。
如果移多位,那么移位次数存放在CL寄存器中。
ROL OPRD,m ;循环左移
ROR OPRD,m ;循环右移
RCL OPRD,m ;带进位循环左移,影响CF和OF
RCR OPRD,m ;带进位循环右移,影响CF和OF
后两条循环指令把进位标志CF也包含在循环的环中,即作为整个循环的一部分
5.转移指令
(1)无条件转移指令
(a)无条件段内直接转移指令
JMP 标号
执行该指令实际操作是把指令中的地址差加到指令指针IP上,使IP的内容为目标地址。
段内无条件直接转移指令中的地址差只用一个字节表示,就称为短转移。
如果用一个字表示,则称为近转移。
段内近跳转: JMP NEAR PTR PROG
段内短跳转: JMP SHORT QUEST
(b)无条件段内间接转移指令
JMP OPRD
转移到操作数OPRD的内容给定的目标地址处。
OPRD可以是通用寄存器,也可以是字存储单元。
例:JMP WORD PTR [2001H]
(c)无条件段间直接转移指令
JMP FAR PTR 标号
例如 JMP FAR PTR NEXT
NEXT是定义在另一个代码段中的标号
实际操作:把指令中包含的目标地址的段值和偏移分别置入CS和IP
(d)无条件段间间接转移指令
JMP OPRD
这条指令使控制无条件地转移到由操作数OPRD内容给定的目标地址处。OPRD必须为双字存储单元。
双字存储单元低字内容送给IP,高字内容送给CS
(2)条件转移指令
根据某标志位或某些标志位的逻辑运算来判别条件是否成立。如果条件成立,则转移。
有符号数间的次序关系称为大于G,等于E,小于L
无符号数间的次序关系称为高于A,等于E,低于B
例子:实现两个无符号数(设在AX和BX中)的比较,把较大的数存放在AX中,把较小的BX中:
CMP AX,BX
JAE OK
XCHG AX,BX
OK: ...
如果要比较的两个数是有符号数:
CMP AX,BX
JGE OK
XCHG AX,BX
OK:...
两个数是否相等可由ZF标志反映。
两个有符号数比较后大小关系由SF和OF一起反映。
当没有溢出(OF=0),若SF=0,a>b
当产生溢出(OF=1),若SF=0,a<b
无符号数使用CF来判别大小关系。
例子:设X,Y均为存放在X和Y单元中的16位操作数,先判断X>50否,如满足条件则转移到TOO-HIGH 去执行,然后做X-Y,如溢出则转移到OVER
去执行,否则计算|X-Y|,并把结果存入RESULT中。
MOV AX,X
CMP AX,50
JG TOO-HIGH
SUB AX,Y
JO OVER
JNS DONE
NEG AX
DONE:MOV RESULT,AX
TOO-HIGH:..
OVER:...
例子:假设有100个16位无符号数存放在从1234:5678H
开始的内存中,现需要求他们的和。设把32位的和保存在DX(高位)和AX寄存器中。
MOV AX,1234H
MOV DS,AX ;置数据段寄存器值
MOV SL,5678H ;置指针初值
MOV AX,0 ;清零32位累加和
MOV DX,AX
MOV CX,100 ;置数据个数计数器
NEXT: ADD AX,[SI] ;求和
ADC DX,0 ;加上可能的进位
INC SI
INC SI
DEC CX ;计数器减1
JNZ NEXT ;如果不为0,那么继续累加
(3)循环指令:
循环指令转移的范围在-126至129之间。
循环指令不影响各标志位。
(a)计数循环指令LOOP:
LOOP 标号
该指令使寄存器CX的值减1,如果结果不为0,则转移到标号。否则顺序执行。
最多可循环65536次。
例子:如下程序片段实现把从偏移1000H开始的512个字节的数据复制到从偏移3000H开始的缓冲区中。
MOV SI,1000H ;置源指针
MOV DL,3000H ;置目标指针
MOV CX,512 ;置计数器初值
NEXT:MOV AL,[SI]
INC SI
MOV [DI],AL
INC DI
LOOP NEXT
(b)等于/全零循环指令LOOPE/LOOPZ
LOOPE 标号
LOOPZ 标号
这条指令使寄存器CX的值减1,当为0或相等时(且ZF等与1),那么转移到标号
例子:字符串中查找第一个非‘A’字符,设字符串长度已保存在CX中,并且DS:DI指向字符串。
如果找到,那么使BX指向该非‘A’字符,如果未找到,那么使BX为0FFFFH
MOV AL,'A'
DEC DI
NEXT: INC DI
CMP AL,[DI]
LOOPE NEXT
MOV BX,DI
JNE OK
MOV BX,-1
OK :...
(c)不等于/非零循环LOOPNE/LOOPNZ
如果结果不为0或不相等时,并且零标志ZF等于0,那么转移到标号,
否则顺序执行,CX减1操作不影响标志。
(d)跳转指令JCXZ
JCXZ 标号
该指令实现当寄存器CX的值等于0时转移到标号,否则顺序执行。
通常该指令用在循环开始前,以便在循环次数为0时,跳过循环体
例子:
JCXZ OK ;如果循环计数为0,就跳过循环
NEXT:... ;
....
LOOP NEXT
OK:...
例子:有一串L字符的字符串存储于首地址为TABLE的存储器中,如果要求在字符串中查找空格
字符,找到则继续执行,如未找到则转到NOT-FOUND去执行:
MOV CX,L
MOV SL,-1
MOV AL,20H
NEXT: INC SI
CMP AL,TABLE[SI]
LOOPNE NEXT
JNZ NOT-FOUND
...
NOT-FOUND: ...