8086常用指令
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
一、通用数据传送指令
MOV:传送,其中 MOVSX 为带符号扩展传送,MOVZX 为带零扩展传送;传送指令功能很直接,就是根据立即数或者源操作数地址,将内存单元或寄存器中的值,或者立即数本身,直接赋予目的操作数。不过这里有一些注意事项:
不准用CS寄存器作为目的数;
不准全用存储器作为两个操作数,比如类似 MOV [BX],[AX];
不准用立即数作为目的数;
不能把立即数送段寄存器,也不能在段寄存器之间传送数据;
PUSH:进栈,POP:出栈;PUSHA/PUSHAD: 全部寄存器进栈;POPA/POPAD:全部寄存器出栈。此类指令均不影响标志位;
XCHG:交换,格式为 XCHG OPR1,OPR2,结果是两者交换,但两者中至少应有一个在寄存器中。此方式不能使用段寄存器,也不影响标志位;
二、累加器专用传送指令
IN:输入
OUT:输出
XLAT:换码
说明:IN 和 OUT 均有长、短两种格式。
长格式形式为:IN AX,PORT(字),其中AX也可以换成AL或EAX,但后面跟的PORT号也要相应变化成字节或双字。对于大于字节的输入指令,执行的操作是(AX)<-(PORT+1,PORT)或(EAX)<-(PORT+3,PORT+2,PORT+1,PORT);
短格式形式为:IN AX,DX(字),当然也能是IN AL,DX(字节)或IN EAX,DX(双字),执行的操作为(AX)<-((DX)+1,(DX)),或(AL)<-((DX)),双字的情况类似,需要传送4个内存单元;
CPU只能用累加器寄存器接收或发送信息,外围设备最多可有65536个IO端口,其中前256个端口可以直接在指令中指定,这就是所谓“长格式”。对于大于或等于256的端口,需要用短格式,将端口号放在DX寄存器里,再用IN或OUT传送信息。
三、地址传送指令
LEA:有效地址传送寄存器。使用格式:LEA REG,SRC,功能是将SRC赋给(REG)。该指令不能使用段寄存器,也不影响标志位。例如如下指令:LEA BX,[BX+SI+0F62H],若(BX)=0400H,(SI)=003CH,则执行后,(BX)=0400+003C+0F62=139EH,仍得到一个地址值。若改为MOV指令,则会得到139EH单元的内容
LDS,LES,LFS,LGS,LSS:分别用于将指针送到DS,ES,FS,GS,SS寄存器。均不影响标志位
注意:虽然MOV也能实现相同功能,如LEA BX,LIST 和MOV BX,OFFSET LIST 均可得到LIST的偏移地址,但OFFSET只能与简单的符号地址相连,因此LEA要更灵活强大些。
四、标志寄存器传送指令
LAHF:Load AH with Flags
SAHF:Store AH into Flags
PUSHF/PUSHFD:标志位进栈
POPF/POPFD:标志位出栈
五、类型转换指令
CBW:字节转为字
CWD:字转为双字
CDQ:双字转4字
BSWAP:字节交换
注:对CBW:AL的内容符号扩展到AH,形成AX中的字。若(AL)的最高位为1,则(AH)=0FFH;对CWD:AX的内容符号扩展到DX,形成DX:AX组中的双字,DX为高位,AX为地位。
六、加法指令
ADD:
不带进位加法
ADC:带进位加法
INC:加一指令
XADD:交换并相加
INC指令不影响标志位,其他几个指令均影响;
ADC指令在完成ADD的功能后还要加上CF(即进位);
XADD指令先把和求出来,然后将目的数放到源数中,最后在把两者的和放到目的数中;
对于CF和OF,需要明白,CF是根据最高有效位是否向高位进位而设,可用于判断无符号数的溢出;而OF是根据数的符号变化来设置的:当结果的符号与操作数的符号相反时,置1,否则置0(两操作数的符号是相同的)。因此可用于表示有符号数的溢出。
七、减法指令
SUB:不带借位减法
SBB:带借位减法
DEC:减一
NEG:求补
CMP:比较
CMPXCHG:比较并交换
SBB指令中执行的操作是:(DST)<-(DST)-(SRC)-CF;
NEG指令即把操作数按位求反并在末位加一,和实际上求反的算法一样;
CMP指令与SUB指令类似,但不保存结果,只设置标志。
八、乘法指令
需要注意的是,乘法指令对除CF和OF外的其他条件码无定义。另外,乘法的源操作数不可为立即数方式。
MUL:乘法。格式为 MUL SRC。执行的操作如下:
字节:(AX)<-(AL)*(SRC)
字:(DX,AX)<-(AX)*(SRC)
IMUL:带符号乘法。个视为 IMUL SRC,操作与SRC大致相同,但源操作数必须为带符号数。
关于标志位设置,对于MUL指令,如果乘积的高一半为0,则CF=OF=0,否则CF=OF=1;对于IMUL指令,如果乘积的高一半是低一半的符号扩展,则CF=OF=0,否则就均为1.
九、除法指令
除法指令对所有条件码均无定义,也不能用立即数寻址。
DIV:无符号整数除法,格式为 DIV SRC。执行操作如下:
字节:16位的被除数默认在AX中,8位除数在(SRC)中,结果的8位商存入AL,8位余数在AH中
字:(AX)<-(DX,AX)/(SRC)的商,(DX)<-(DX,AX)/(SRC)的余数
IDIV:带符号数乘法,格式与DIV相同。
十、逻辑指令
AND:与。格式为:AND DST,SRC。操作为:(DST)<-(DST) && (SRC)
OR:或。格式为:OR DST,SRC。操作为:(DST)<-(DST)||(SRC)
NOT:非。格式为:NOT OPR。操作为:(OPR)<-!(OPR)
XOR:异或。格式为:XOR DST,SRC。操作为:(DST)<-(DST) xor (SRC)
TEST:测试。格式为:TEST OPR1,OPR2。操作和AND差不多,但只设置条件位,不影响其他的
十一、移位指令
左移:SHL,SAL,ROL
右移:SHR,SAR,ROR
上面的指令中,H=逻辑,A=算术,O:循环。
另外,有如下需要注意的地方:
逻辑左移与算术左移等效:即把源段中的位依次左移到CF中,同时从右边补0;
逻辑右移是在左边装入0;算术右移则把左边首位重复再装入左边;右边的移出去后进入CF;
循环移位,均是把移出去的位又从对面装入,并影响CF;
通用格式:<指令> OPR,CNT。意义:把OPR的内容移
动CNT次。在8086中可用CL代替CNT。
十二、串处理指令
INS:串输入。格式为:INS DST,DX。这种方式需要在操作数中体现是字节、字或双字操作。也可以在指令中体现,用INSB、INSW或INSD。该指令把端口号在DX中的I/O空间的字节、字或双字传送到附加段中由DST指向的内存单元中。
OUTS:串输出。格式为:OUTS DX,SRC,当然也有OUTSB/OUTSW/OUTSD几种指定格式的形式,格式与INS类似。该指令把由源变址寄存器所指向的存储器中的字节、字或双字传送到端口号在DX寄存器中的I/O端口去。
MOVS:串传送。格式为:MOVS DST,SRC,当然也有MOVSB/MOVSW等。格式规定一样。该指令功能为:把由源变址寄存器指向的数据段中的一个字(或字节、双字)传送到目的寄存器指向的附加段中的一个字(或字节、双字)中,同时根据扫描方向标志及数据类型对源变址和目的变址寄存器进行必要修改(类似于修改下标),
REP指令:格式为:REP <串处理指令>,如REP INS等。执行规则是和循环类似,当CX=0时退出重复。由于这些串处理指令都只一次处理一个单位的数据,因此一般都需要与REP指令结合起来实现批量的数据传送。
结合REP指令的串处理指令用法实例: 若mess1,mess2是data段中指定的两个字符串,其中mess1在data中,为源串;mess2在extra中,为目的串
mov ax,data;这两句设置标准数据段
mov ds,ax
...
mov ax,extra;这两句设置扩展数据段
mov ex,ax
...
lea si,mess1;赋予源变址SI
lea di,mess2;赋予目的变址DI
mov cx,17;指定重复次数
CLD;方向标志置零(从左向右扫描)
rep movsb
...
此外,还有带条件的串重复指令,如REPE/REPZ和REPNE/REPNZ。这两种指令同时也要考虑CX计数器的值,但可能在计数器不为零时,因为不满足下面的条件而提前退出:
REPE/REPZ:当相等/为零时重复串操作;
REPNE/REPNZ:当不相等/不为零时重复操作;
除了上述指令,还有CMPS和SCAS。分别实现串比较和扫描。这两个指令只影响标志位:
SCAS DST:SCASB(字节),SCASW(字),SCASD(双字)。功能:把AL/AX/EAX的内容与由目的变址指向的在附加段中的一个字节、字或双字进行比较(其实也是相减),根据结果设置条件码。
CMPS:同样有3中数据格式,功能:把有源变址寄存器指向的数据段中的一个字节、字或双字与由目的变址寄存器所指向的附加段中的一个字节、字或双字相减,根据结果设置条件码。
最后,有两个串存取指令:
LODS SRC:该指令把由源变址指向的数据段中某单元的内容送到AL,AX或EAX中,并根据方向标志和数据类型修改源变址寄存器内容。
该指令允许段跨越前缀来调用非数据段的存储区,同时不影响标志位。一般,该指令不与REP联用。
STOS DST:该指令把AL,AX或EAX的内容存入由目的变址寄存器指向的附加段的某单元中,并根据DF的值及数据类型修改目的变址寄存器的内容。该指令也不影响标志,而当它与REP联用时,可把AL,AX或EAX的内容存入一个长度为Count的缓冲区中(Count一般也是用CX指定)。这个指令在初始化一段缓冲区时很有用。
十三、直接(无条件)转移指令
JMP SHORT OPR:段内直接短转移,执行操作为(IP)<-(IP)+(OPR)8位偏移量;
JMP NEAR PTR OPR:段内直接近转移,执行操作为(IP)<-(IP)+(OPR)16位偏移量;
JMP WORD PTR OPR:段内间接近转移,执行操作为(IP)<-(EA)。其中EA为有效地址,指定下一条指令所在位置,其值由OPR的寻址方式确定,除了不能用立即数,其他寻址方式均可。
JMP FAR PTR OPR:段间直接远转移。由于不在一个段,因此在改变IP的同时还要改变CS。执行操作为(IP)<-OPR的段内偏移地址;(CS)<-OPR所在段的段地址
JMP DWORD PTR OPR:执行的操作为(IP)<-(EA);(CS)<-(EA+2)
JMP指令不影响条件码。
十四、条件转移指令
对单个条件标志比较,并由结果转移
JZ(JE):当结果为0或相等则跳转。相反:JNZ(JNE);
JS:当结果为负则跳转。相反:JNS;
JO:当溢出则跳转。相反:JNO;
JP(JPE):当奇偶位为1则跳转。相反:JNP(JPO);
JB(JNAE):当低于或CF=1则转移。相反:JNB(JAE),不低于则转移;
对两个无符号数的比较,并由结果转移
JB(JNAE),相反JNB(JAE):与上面第五点相同。测试条件:CF=1 / CF=0;
JBE(JNA):不高于则转移。相反:JNBE(JA)。测试条件:CF||ZF=1 / CF||ZF=0;
对两个带符号比较,并由结果转移
JL(JNGE):小于则转移。相反:JNL(JGE)。测试条件:SF xor OF=1 / SF xor OF=0;
JLE(JNG):不大于则转移。相反:JNLE(JG)。测试条件:(SF xor OF)||ZF=1 / (SF xor OF)||ZF=0。
注意:上述指令中,“小于”和“低于”的意义不同。前缀对应无符号数,后者对应有符号数,因此虽然JBE和JLE似乎差不多,但其判断条件并不同。
十五、循环指令
LOOP:当CX!=0时循环;
LOOPZ(LOOPE):当ZF=1且CX!=0时循环;
LOOPNZ(LOOPNE):当ZF=0且CX!=0时循环。
注:每次循环时,CX的值会自动减一。
十六、中断指令
INT:调用中断;
INTO:如果溢出则中断。
常用中断在后面介绍。
十七、标志设置指令
CLC:CF置零
CMC:CF取反
STC:CF置一
CLD:DF置零
STD:DF置一
CLI:IF置零,即中断标志置零
STI:IF置一
最后,有一些技巧和经验需要总结一下:
用LENGTH伪操作只能取得DUP(?)前面的值,比如 buffer db 40 dup('a') 这条指令,如果用LENGTH,可用得到4
0。
寻址时,若是相对/变址/基址寻址模式,则求物理地址时务必加上数据段DS的物理地址
对常用的单位为字的操作,则每次指针量递增或递减时均跳2个。道理很简单,因为多数时候的操作都是针对字的,这意味着要占用2个内存单元。
16位指令,进栈时的操作:(SP)<-(SP)-2,((SP)+1,(SP))<-操作数。出栈时相反,SP要上移两个单位。
程序调用中断时,自动入栈CS,IP,PSW共3个字;子程序中断时,自动入栈CS,IP共2个字。
返回DOS中断调用:INT21 4CH
若定义嵌套数组,如ARRAY DB 100 DUP (0,2 DUP (1,2),3),则内存单元分配的情况是将(1,2)重复2次,作为外层数组的第二个元素,第一个和第三个元素分别是0和3。这样整个再重复100次。
逻辑指令中,除了NOT外,其余均会把CF和OF置为0
定义数据时,若要用一个字符串,则最后要用'$'结尾。如 MSG DB '***HELLO WORLD','$'。
关于DOS I/O(INT21中断调用)
AH=01(键盘输入并回显),AL=输入的字符
AH=02(输出字符),DL=要输出的字符
AH=09(输出字符串),DS:DX=串地址,并需要以'$'结尾
AH=0A(输出字符串),DS:DX=输入缓冲区首地址,其值(DS:DX)=能输入的最大字符数,(DS:DX+1)=实际输入字数
8086机器中,只有IF,CF,DF三种标志可用指令来设置
NOT的优先级比其他逻辑运算高
使用移位指令时,一般大于1并小于256的次数,都放在CL中
堆栈只能以字为单位
XLAT指令的功能:(AL)<-((BX)+(AL))
在内存单元中取数的方法:
MOV CX,WORD PTR [NUM]
MOV BX,WORD PTR DATA[SI](这里SI作为下标使用)
呼!这么多!没想到。。。。终于总结得差不多了,可能有疏漏和错误,欢迎朋友们指正,共同学习!