版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
80x86/8088指令系统
8086/8088的指令系统丰富,而且指令的功能也强。 大多数指令既能处理字数据,又能处理字节数据。 指令系统可分为如下6个功能组: (1)数据传送 (2)算术运算 (3)逻辑运算 (4)串操作 (5)程序控制 (6)处理器控制 汇编语言中,指令语句可由四部分组成,一般格式如下:
[标号:]指令助记符
[操作数1[,操作数2]][;注释]
(一)数据传送指令 可以实现数据传送的指令可分为:传送指令,交换指令,地址传送指令,堆栈操作指令,标志传送指令。
1.传送指令 其格式如下:MOVDST,SRC
源操作数可以是累加器、寄存器、存储单元及立即数, 目的操作数可以是累加器、寄存器和存储单元。 传送不改变源操作数。 传送指令能实现下列传送功能:
(1)CPU内部寄存器之间的数据传送。例如:
MOVAH,AL MOVDL,DH MOVBP,SP MOVAX,CS
注意:源和目的操作数不能同时是段寄存器;代码段寄存器CS不能作为目的数;指令指针IP不能作为源,也不能作为目的操作数。
(2)立即数送至通用寄存器或存储单元。例如:
MOVAL,3 MOVSI,-5 MOVVARB,-1;VARB是变量名,代表一个存储单元
MOVVARW,3456H;VARW是一个字变量
MOV[SI],6543H
注意: 立即数不能直接送到段寄存器, 立即数永远不能作为目的操作数。 (3)寄存器与存储器间的数据传送。例如:
MOVAX,VARW MOVBH,[DI] MOVDI,ES:[SI+3] MOVVARB,DL MOVDS:[BP],DL MOVVARW,DS MOVES,VARW
注意: 源操作数和目的操作数不能一个为字节另一个为字;
源操作数和目的操作数不能同时是存储器操作数(串指令除外)
如果要在两个存储单元间传送数据,怎么办呢? 那么可利用通用寄存器过渡的方法进行: 例如:把字变量VARW1的内容送到字变量VARW2 MOVAX,VARW1 MOVVARW2,AX
这种方法也适用于段寄存器间的数据传送。例如:
MOVAX,CS MOVDS,AX
请熟悉下面语句:
MOVAL,‘D’; 立即数(字符’D’的ASCII码)送到AL寄存器
MOVBX,OFFSETTABLE
;把TABLE的偏移地址(不是内容)送到BX寄存器,OFFSET为属性操作符。 2.交换指令 利用交换指令可方便地实现通用寄存器与通用寄存器或存储单元的数据交换。交换指令的格式如下:
XCHGOPRD1,OPRD2
此指令把操作数OPRD1的内容与操作数OPRD2的内容交换。操作数同时是字节或字。 例如: XCHGAL,AH XCHAGSI,BX OPRD1和OPRD2可以是通用寄存器或存储单元。但不能包括段寄存器,也不能同时是存储单元,还不能有立即数。 对于要交换的存储单元,可有多种寻址方式。 例如:XCHGBX,[BP+SI]
如指令执行前:(BX)=6F30H,(BP)=0200H,(SI)=0046H, (SS)=2F00H,(2F246)=4154H
指令执行后(BX)=4154H,(2F246H)=6F30H 3.地址传送指令
8086/8088有3条地址传送指令。 (1)LEA(LoadEffectiveAddress) LEAREG,OPRD
把操作数OPRD的有效地址传送到操作数REG。
操作数OPRD必须是指存储器, 操作数REG必须是一个16位的通用寄存器。 例如:
LEAAX,BUFFER ;BUFFER是变量名
LEASI,[BP+SI+4]
例如:LEABX,[BX+SI+0F62H]
如执行指令前(BX)=0400H,(SI)=003CH
执行指令后(BX)=0400+003C+0F62=139EH
(2)LDS(LoadpointerintoDS)
段值和段内偏移构成32位指针(两个16位地址)。
LDS用于传送32位地址指针,格式如下:
LDSREG,OPRD
执行的操作: (REG)<-(SRC) (DS)<-(SRC+2)
该指令把操作数OPRD中所含的一个32位地址指针的段值部分送到数据段寄存器,把偏移部分送到指令给出的通用寄存器REG。操作数OPRD必须是一个32位的存储器操作数。
32位地址指针的偏移部分存储在双字变量的低地址字中, 段值部分存放在高地址字中 例如:LDSSI,[10H]
如执行指令前(DS)=C000H,(C0010H)=0108H, (C0012H)=2000H.
执行指令后(SI)=0180H,(DS)=2000H
(3)LES(LoadpointerintoES) LES指令也是用于传送32位地址指针,格式如下:
LESREG,OPRD
执行的操作: (REG)<-(SRC) (ES)<-(SRC+2)
例如:LESDI,[BX]
如执行指令前:(DS)=B000H,(BX)=080AH, (B080AH)=05AEH,(B080CH)=4000H
执行指令后(DI)=05AEH,(ES)=4000H
例如:如果TABLE为数据段中0032单元的符号名,其中存放的内容为1234H,试问以下两条指令有什么区别?
MOVAX,TABLE LEAAX,TABLE
第2条效果与
MOVAX,OFFSETTABLE
相同。分析其中的数据传送指令 3.堆栈操作指令 在8086/8088系统中,堆栈是一段RAM区域,是以“后进先出”方式工作的一个存储区。 称为栈底的一端地址较大(高地址), 称为栈顶的一端地址较小(低地址)。 堆栈的段值在堆栈段寄存器SS中,堆栈指针SP始终指向栈顶。 堆栈的存取必须以字位单位。 堆栈操作指令分为2种: (1)进栈指令PUSH
格式:PUSHSRC SRC可以是通用寄存器、段寄存器也可以是字存储单元。 执行的操作:把源数据压入堆栈。步骤为:
1.堆栈指针寄存器器SP的值减2;
2.把源操作数SRC送入由SP所指的栈顶。
例如:PUSHAX
假设(AX)=2107H
(2)出栈指令POP
格式:POPDST
执行的操作:从堆栈顶弹出一个字数据到目的操作数DST。
步骤为:
1.把堆栈指针寄存器SP所指的字数据送往目的操作数DST;
2.堆栈指针寄存器器SP的值加2。
DST可以是通用寄存器、段寄存器(CS除外),也可以是字存储单元 接前面例子:
POPAX
执行后: (AX)=2107H
注意:
PUSH和POP只能作字操作。 它们可以使用除立即数之外的其它寻址方式。 但POP指令不运行访问CS寄存器。 下面程序说明堆栈的一种用途,请熟悉。
PUSHAX; 保护AX PUSHBX; 保护BX ….. POPBX; 恢复BX POPAX; 恢复AX
例:假设(SS)=2250H,(SP)=0140H
如果在堆栈中存入5个数据,则栈顶的物理地址是多少? 未存入数据之前物理地址=22500+0140=22640H
存入5个数据,栈顶的物理地址为:
22640–0A=22636H
如果又从堆栈中取出3个数据,则栈顶的物理地址是多少?
22636+6=2263CH
通过前面讲授的指令,数据交换至少有3种方式: 传送指令、交换指令、堆栈指令 例如:将寄存器AX与SI的内容交换。 用MOV指令,利用通用寄存器过渡的方式:
MOVBX,AX MOVAX,SI MOVSI,BX
用交换指令XCHG XCHGAX,SI
用堆栈指令
PUSHAX; PUSHSI; POPAX; POPSI;
其它传送操作指令 累加器专用传送指令:
IN OUT XLAT
标志寄存器传送指令:
LAHF SAHF PUSHF POPF
(二)加减运算指令
1.加法指令ADD
其格式如下:ADDOPRD1,OPRD2
执行的操作:(OPRD1)<-(OPRD1)+(OPRD2)
例如:
MOVAX,7896H; AX=7896H,各标志位保持不变
ADDAL,AH; AL=0EH,即AX=780EH ;CF=1,ZF=0,SF=0,OF=0,AF=0,PF=0
又如: 例:ADDDX,0F0F0H
若执行前(DX)=4652H,则执行后(DX)=3742H,
ZF=0,SF=0,CF=1,OF=0
例:ADDAX,4321
若执行前(AX)=62A0,则执行后(AX)=A5C1H,
ZF=0,SF=1,CF=0,OF=1,加法操作影响标志位。 2.带进位加指令ADC(ADdwithCarry) 其格式如下:ADCOPRD1,OPRD2
(OPRD1)<-(OPRD1)+(OPRD2)+CF
例如,执行两个双精度数(32位)的加法。设目的操作数放在DX和AX中,其中DX存放高位字。源操作数放在BX,CX中,其中BX存放高位字。 如执行前 (DX)=0002H, (AX)=0F365H, (BX)=0005H, (CX)=0E024H
指令序列位: ADDAX,CX ADCDX,BX
执行第一条指令后,(AX)=D389H,SF=1,ZF=0,CF=1,OF=0
执行第二条指令后,(DX)=0008H,SF=0,ZF=0,CF=0,OF=0
运算结果:(DX)=0008H,(AX)=D389H
从上面例子可以看出:为实现双精度加法,必须用两条指令分别完成低位字和高位字的加法。在高位字相加时,应该使用ADC指令以便把前一条ADD指令作低位字加法所产生的进位值加入高位字之内。带符号双精度数的溢出,应该根据ADC指令的OF位来判断,而作低位加法用的ADD指令的溢出标志在双精度数相加时,是无意义的。 3.加1指令INC(INCrement) 其格式如下:INCOPRD
(OPRD)<-(OPRD)+1
功能:对操作数加1. OPRD可以是通用寄存器,也可以是存储单元。 指令执行的结果影响ZF、SF、OF、PF、AF,但不影响CF.
改指令主要用于调整地址指针和用于计算器。
例:写出把首地址为BLOCK的字数组的第6个字送到DX寄存器的指令。 (1)使用寄存器间接寻址
MOVBX,OFFSETBLOCK ADDBX,000AH MOVDX,[BX]
(2)寄存器相对寻址
MOVBX,OFFSETBLOCK MOVDX,[BX+000AH]
其中,MOVBX,OFFSETBLOCK还可以写成:
LEABX,BLOCK
例:在TABLE数组中依次存储了7个字数据,紧接着是名位ZERO的字单元,表示如下:
TABLEDW23,36,2,100,3200,54,0 ZERODW?
(1)如果BX包含数据TABLE的初始地址,请编写指令将数据0传送给ZERO单元。
MOVAX,[BX+0CH] MOVZERO,AX
(2)如果BX包含数据0在数组中的位移量,请编写指令将数据0传送给ZERO单元。
MOVAX,[TABLE+BX] MOVZERO,AX
例:试分析下列程序段执行后,AX的内容是是多少?
Datasegment Adw0 Bdw0 Cdw230,20,54 Dataends Codesegment … MOVBX,OFFSETC MOVAX,[BX] MOVB,AX MOVAX,2[BX] ADDAX,B … Codeends 4.减法指令SUB(SUBtraction) 其格式如下:SUBOPRD1,OPRD2
执行的操作:(OPRD1)<-(OPRD1)-(OPRD2)
例:SUB[SI+14H],0136H
若执行前(DS)=3000H,(SI)=0040H,(30054H)=4336H
则执行后(30054H)=4200H,
ZF=0,SF=0,CF=0,OF=0
例:SUBDH,[BP+4]
若执行前(DH)=41H,(SS)=0000H,(BP)=00E4,(000E8)=5AH
则执行后(DH)=E7H,
ZF=0,SF=1,CF=1,OF=0,
加法操作影响标志位。
减法的OF位设置方法为:若两个数的符号相反,而结果的符号与减数(减号后那个数)相同,则OF=1,说明结果是错误的。 5.带借位减法指令SBB(SUBtractwithBorrow) 其格式如下:SBBOPRD1,OPRD2
执行的操作:(OPRD1)<-(OPRD1)-(OPRD2)-CF
例: SBBAL,DL SBBDX,AX
该指令主要用于多字节相减的场合。
6.减1指令DEC(DECrement) 格式:DECOPRD
执行的操作:(OPRD)<-(OPRD)-1
例如:DECVARB;VARB是字节变量。
OPRD可以是通用寄存器,也可以是存储单元。 指令执行的结果影响ZF、SF、OF、PF、AF,但不影响CF.
改指令主要用于调整地址指针和用于计算器。 7.取补指令NEG(NEGate) 其格式如下:NEGOPRD
执行的操作:(OPRD)<--(OPRD)
例:
NEGAL
如在字节操作时,对-128取补,或在字操作时对-32768取补,则操作数不变,但是OF被置1。其它均为0.
操作数可以是寄存器,也可是一存储单元。 此指令的执行结果影响CF、ZF、SF、OF、AF和PF。 操作数位0时,求补运算的结果使CF=0,其它情况则均为1. 8.比较指令CMP(CoMPare) 其格式如下:CMPOPRD1,OPRD2
这条指令将操作数OPRD1减去OPRD2,但是运算结果不送到OPRD1,但是,要影响到标志位CF、ZF、SF、OF、AF、PF.
例:
CMPSI,DI CMPCL,5 CMPDX,[BP-4]
比较指令主要是用于比较两个数的关系,如大小。 根据ZF是否为0,判断两者是否相等; 如果两者是无符号数,可根据CF判断大小; 如两者为有符号数,则要根据SF和OF判断大小。
例:设X,Y,Z均为双精度数,它们分别存放在地址为X,X+2;Y,Y+2;Z,Z+2的存储单元中。下列指令序列实现(X+Y+24-Z),并将结果放在W和W+2单元中。
MOVAX,X MOVDX,X+2 ADDAX,Y ADCDX,Y+2 ADDAX,24 ADCDX,0 SUBAX,Z SBBDX,Z+2 MOVW,AX MOVW+2,DX
例:设在当前数据段的偏移地址2000H单元内,含有两指针,它们是两个16位变量的偏移地址和段地址,试写出把该变量装入AX的指令序列。
MOVBX,[2000H] MOVES,[2002H] MOVAX,ES:[BX]
例:写出执行以下计算的指令指令序列。
Z←W+(Z-X)
其中X,W,Z均为存放16位带符号数单元的地址。
方法1:
MOVAX,Z MOVBX,X SUBAX,BX MOVBX,W ADDAX,BX MOVZ,AX
方法2:
MOVAX,Z SUBAX,X ADDAX,W MOVZ,AX
执行下列指令序列后,AX寄存器中的内容是什么?
TABLEDW10,20,30,40,50 RETURNDW3 … MOVBX,OFFSETTABLE ADDBX,RETURN MOVAX,[BX]
(AX)=1E00H
指出下列指令的错误: (1)MOVAH,BX
位数不匹配 (2)MOVAX,[SI][DI] SI,DI同为变址寄存器 (3)CMP15,BX
目的操作数不能为立即数 (4)PUSHBL PUSH,POP只能是对字单元进行操作 (5)POPCS
代码段寄存器不能作为目的操作数 (6)MOV[BX],[SI]
源操作数和目的操作数不能同时为存储器单元内容 (7)CMPOP1,OP2(OP1,OP2是字节变量)
字节变量相当于存放于存储器,“源目”不能同时为存储器
执行下列指令序列后,AX=?,BX=? MOVAX,0123H MOVBX,0321H PUSHAX PUSHBX POPAX POPBX
AX=0321H,BX=0123H (三)乘除运算指令 乘除运算指令分为无符号数运算和有符号数运算指令,这点与加减法运算指令不同。 乘除运算对标志位的影响有些特别。
1.乘法指令 在乘法指令中,一个操作数总是隐含在寄存器中(AL或AX),另一个操作数可以采用除立即数以外的任一种寻址方式。 (1)无符号数乘法指令MUL(MULtiply) 格式:MULOPRD
在乘法指令里,目的操作数必须是累加器。 两个8位数相乘得到的是16位乘积,存放于AX中;两个16位数相乘得到的是32位乘积,存放于DX(高位字)和AX(低位字)中。 如果乘积结果的高半部分(字节相乘时为AH,字相乘时为DX)不等于0,则CF=1,OF=1。否则,CF=0,OF=0.
(2)有符号数乘法指令IMUL(sIgnedMULtiply) 格式:IMULOPRD
这条指令把被乘数和乘数均作为有符号数。 如果乘积结果的高半部分(字节相乘时为AH,字相乘时为DX)不是低半部分的符号扩展,则标志CF=1,OF=1。否者,CF=0,OF=0。 所以,MUL和IMUL指令运行后,可根据CF和OF是否等于1来判断AH或DX中含有的结果是否为有效数。 例:如(AL)=B4H,(BL)=11H, 求MULBL和IMULBL后的乘积值?
(AL)=B4H,无符号数为180D,带符号数为-76D (BL)=11H,无符号数位17D,带符号数为17D
执行MULBL结果:(AX)=3060D=0BF4H,CF=OF=1
执行IMULBL结果:(AX)=-1292D=FAF4H,CF=OF=1 2.除法指令 在除法指令中,被除数总是隐含在寄存器AX(除数是8位)或者DX和AX(除数是16位)中,另一个操作数可以采用除立即数以外的任一种寻址方式。 (1)无符号数除法指令DIV(DIVision) 格式:DIVOPRD
字节操作时:
(AL)<-(AX)/(OPRD)的商,(AH)<-(AX)/(OPRD)的余数; 字操作时:
(AX)<-(DX,AX)/(OPRD)的商,
(DX)<-(DX,AX)/(OPRD)的余数.
如果除数是0,或者在8位数除时商超过8位,或者在16位除时超过16位,则认为是溢出,引起0号中断。 除法指令对标志位的影响无定义。
(2)有符号数除法指令IDIV(sIgnedDIVision) 格式:IDIVOPRD
这条指令把被除数和除数均作为有符号数。 字节操作时: 如果除数是0,或者商太大 (字节除时超过127,字除时超过32767) 或者商太小 (字节除时超过-127,字除时超过-32767) 则引起0号中断。 例如:(AX)=0400H,(BL)=B4H,
执行DIVBL的结果是
(AH)=124D=7CH(余数),(AL)=5D=05H(商) 执行IDIVBL的结果是
(AH)=36D=24H(余数),(AL)=-13D=F3H(商) 3符号扩展指令 由于除法指令隐含使用字被除数或双字被除数,所以当被除数为字节,或者除数和被除数均为字时,需要在除操作前扩展被除数。 (1)字节转为字指令CBW(ConvertBytetoWord) 格式:CBW
功能:把寄存器AL中的符号扩展到寄存器AH中。 例如: MOVAX,3487H;AX=3487H,AL=87H CBW ;AX=FF87H
这条指令不影响各标志位。 (2)字转为位双字指令CWD(ConvertWordtoDoubleword)
格式:CWD
功能:把AX中的符号位扩展到寄存器DX。 例如: MOVAX,4567H ;AX=4567H CWD ;AX=4567H,DX=0
例如:计算表达式(X*Y+Z-1024)/75之值。 假设其中的X、Y、Z均为16位带符号数,分别存放在名为XXX、YYY、ZZZ的变量单元中。把最后计算结果的商在AX中,余数保存在DX中。
MOVAX,XXX IMULYYY ;计算X*Y,结果已扩展至32位
MOVCX,AX MOVBX,DX ;乘积保存到BX、CX中
MOVAX,ZZZ CWD ;把ZZZ也扩展成32位
ADDAX,CX ;再计算和
ADCDX,BX SUBAX,1024 ;再计算差
SBBDX,0 MOVCX,75 IDIVCX ;最后计算商和余数
(四)逻辑运算和移位指令
1.逻辑运算指令 (1)否操作指令 格式:NOTOPRD
这条指令把操作数OPRD取反,然后送回OPRD。 操作数可以是通用寄存器,也可以是存储器操作数。 此指令对标志没有影响。 (2)与操作指令AND
格式:ANDOPRD1,OPRD2
这条指令对两个操作数进行按位的逻辑“与”运算,结果送到目的操作数OPRD1。该指令执行后,标志CF=0,OF=0,标志PF、ZF、SF反映运算结果,标志AF未定义。
与操作指令主要用在使一个操作数中的若干位维持不变,而另外若干位清0的场合。 把要维持不变的这些位与“1”相“与”,而把要清位0的这些位与“0”相“与”就能达到这样的目的。
(3)或操作指令OR
格式:OROPRD1,OPRD2
这条指令执行后,标志CF=0,标志OF=0,标志PF,ZF,SF反映运算结果,标志AF未定义。 某个操作数与自己相“或”,则值不变,但进位标志CF清0。
或指令主要用在使一个操作数中的某些位维持不变,而另外若干位设置为1的场合。 (4)异或操作指令XOR
格式:XOROPRD1,OPRD2
这条指令对两个操作进位按位的逻辑“异或”运算,结果送到目的操作数OPRD1。该指令执行以后,标志CF=0,OF=0,标志PF,ZF,SF反映运算结果,AF未定义。 某个操作数自己与自己相“异或”,则结果为0,并使CF清0。
异或操作主要用在使一个操作数中的若干位维持不变,而另外若干位置取反的场合。 把要维持不变的这些位与“0”相“异或”,而把要去反的位与“1”相异或就能实现改功能。
(5)测试指令TEST
格式:TESTOPRD1,OPRD2
这条指令和指令AND类似,也把两个操作数进行按位“与”,但结果不送到操作数OPRD1。 该指令执行后,标志ZF、PF和SF反映运算结果,标志CF和OF被清0。 该指令常用于检测某些位是否为1,但又不希望改变原操作数的场合。 例如:要检查AL中的位6或位2是否有一位是1。
TESTAL,01000100B ;符号B表示二进制数 或
TESTAL,44H
如果位6和位2全为0,那么在执行上面的指令后,ZF被置为1,否者ZF被清0。
举例:
1.要求屏蔽0、1两位,可用AND指令并设置常数FCH。
MOVAL,BFH ;将待屏蔽的数送至AL ANDAL,FCH
执行后(AL)=BCH 2.要求第5位置1,可用OR指令
MOVAL,43H ;将待处理的数送至AL ORAL,20H
执行后(AL)=63H 3.要测试操作数的某位是否为1,则可先把该操作数求反,然后用TEST指令测试。 如要测试AL寄存器中第2位是否为1,如是则转移到EXIT:
MOVDL,AL NOTDL TESTDL,00000100B
JEEXIT 2.一般移位指令 (1)算术左移或逻辑左移指令,SAL/SHL (ShiftArithmeticLeft或ShiftLogicLeft)
算术左移和逻辑左移进行相同的操作,尽管为了方便提供了两个助记符,但只有一条机器指令。具体格式如下:
SALOPRD,m或者
SHLOPRD,m
算术左移SAL/逻辑左移SHL指令把操作数OPRD左移m位。每移动一位,右边用0补足一位,移出的最高位进入标致位CF。 例如:
MOVAL,8CH SHLAL,1;AL=18H,CF=1,PF=1,ZF=0,SF=0,OF=1 MOVCL,6 SHLAL,CL;AL=0,CF=0,PF=1,ZF=1,SF=0,OF=0
只要左移以后的结果未超出一个字节或一个字的表达范围,那么每左移一次,原相当于乘以2。
例:把寄存器AL中的内容(设为无符号数)乘10,结果放在AX中。
XORAH,AH ;(AX)=0 SHLAX,1 ;2X MOVBX,AX ;暂存2X SHLAX,1 ;4X SHLAX,1 ;8X ADDAX,BX ;8X+2X (2)算术右移指令SAR(ShiftArithmeticRight) 格式:SAROPRD,m
该指令是操作数右移m位,同时每移一位,左边的符号位保持不变,移入位与符号位一致,移出的最低位进入标致位CF。 例如: MOVCL,5 SAR[DI],CL
如执行前:(DS)=F800H,(DI)=180AH,(F980A)=0064H/8064H
执行后:(F980A)=0003H/FC03H
(3)逻辑右移指令SHR(ShiftlogicRight) 格式:SHROPRD,m
该指令是操作数右移m位,同时每移一位,左边用0补足,移出的最低位进入标致位CF。 对于无符号数而言,逻辑右移一位相当于除以2。
在汇编语言程序设计中,经常需要对以位为单位的数据进行合并和分解处理。这种操作一般是通过移位指令和逻辑运算指令执行。 例如:假设DATA1和DATA2各长4位,分别存放在AL寄存器的低4位和高4位中,现要把它们分别存放到BL寄存器和BH寄存器的低4位中。
MOVBL,AL ANDBL,0FH ;得DATA1 MOVBH,AL MOVCL,4 SHRBH,CL ;得DATA2 3.循环移位指令
8086/8088有四条循环指令,这些指令可以一次只移移位;也可以一位移多位,那么移位次数存放在CL寄存器中。 这些指令格式如下:
ROLOPRD,m (RotateLeft)
ROROPRD,m RCLOPRD,m (Rotateleftthroughcarry) RCROPRD,m
其中,m是移位次数,或为1或为CL。操作数OPRD可以是通用寄存器,可以是存储器操作数。前两条循环指令没有把进位标志CF包含在循环的环中;后两条循环指令把进位标志CF包含在循环的环中,即作为整个循环的一部分。 对于不带进位的循环移位,如果操作数是8位,则移位8次后操作数就能复原;如果操作数是16位,则移位16次后就能复原。 对于带进位的循环指令而言,如果操作数是8位,那么在移位9次后操作数就能复原;如果操作数是16位,则要复原需要移位17次。
MOVCL,9 RCRAL,CL
通过循环移位指令和其它移位指令的结合,可以实现两个或多个操作数的重新结合。 例如:实现把AL的高4位和低4位交换
ROLAL,1 ROLAL,1 ROLAL,1 ROLAL,1
例(AX)=0012H,(BX)=0034H,要求把他们装配在一起形成(AX)=1234H MOVCL,8 ROLAX,CL ADDAX,BX
例如:试分析下面程序完成什么功能?
MOVCL,4 SHLDX,CL MOVBL,AH SHLAX,CL SHRBL,CL ORDL,BL
(五)串处理指令
回忆一下:同学们学习了C语言,知道了哪些关于串操作的函数?
(五)串处理指令
1.串拷贝 利用C语言编写串拷贝函数
voidcopy_str(char*dst,char*src,intlen) { inti; for(i=0;i<len;i++) {
*dst=*src; dst++; src++; } } src:源串
dst:目标串
len:拷贝长度
++:拷贝方向 关键字for:循环过程
(1)利用汇编指令进行串拷贝
src:源串 ——〉由SI寄存器给出
dst:目标串 ——〉由DI寄存器给出
len:拷贝长度 ——〉由CX寄存器给出
++:拷贝方向 ——〉由PSW的DF给出(CLD,STD设置) 关键字for:循环过程 ——〉由指令REP给出 进一步讲,操作对象由MOVS/MOVSB/MOVSW给出 其中MOVS指令的格式为:
MOVSDST,SRC
应在操作数种明确指明是字还是字节。 例:MOVSES:BYTEPTR[DI],DS:[SI] MOVSES:WORDPTR[DI],DS:[SI]
而MOVSB和MOVSW无需再专门写出操作数。 结合起来:REPMOVSDST,SRC
或REPMOVSB/REPMOVSW
注意:(1)目的操作数必须放在附加段中; (2)源操作数原则上应放在数据段中,但可通过段前缀改变串拷贝程序。左边源串位于数据段,右边源串位于附加段:
(2)存入串指令
STOSDST STOSB STOSW
功能:把AL或AX的内容存入由DI指定的目标串中。 存入的个数由CX寄存器决定。
(3)从串取指令
LODSSRC LODB LODW
功能:把由SI指定的源串中取内容并送至AL或AX寄存器。 存入的个数由CX寄存器决定。
2.串比较 (1)利用C语言编写串比较函数
intcmp_str(char*s1,char*s2,intlen,int*left) { inti; *left=len; for(i=0;i<len;i++) {
(*left)--; if(*s1==*s2)continue; if(*s1>*s2)return1;//串1比串2大
if(*s1<*s2)return-1; //串1比串2小
}
return0; //串1与串2相等
} ==:循环条件、len最大比较个数
0、-1、1:比较结果标志 *left:未比较的个数
(2)利用汇编指令进行串比较
s1:源串 ——〉由SI寄存器给出
s2:目标串 ——〉由DI寄存器给出
len:比较长度 ——〉由CX寄存器给出
++:拷贝方向 ——〉由PSW的DF给出(CLD,STD设置) 循环条件 ——〉由指令REPE/REPZ给出 进一步讲,对应单元内容相同或为0时则重复。
重复什么?CMPS/CMPSB/CMPSW。 其中CMPS需要指出所比较的两个串
CMPSSRC,DST
而CMPSB/CMPSW则无需显式地给出这两个串。 结合起来:REPECMPSSRC,DST
或 REPECMPSB/REPECMPSW
结果:
(SI)、(DI)不相匹配字符的下一个字符地址;
(CX)剩下未比较的字符个数。
CMPS/CMPSB/CMPSW会改变PSW,即反映串之间的大小关系。比较“hello!”和“helle.”,下列程序输出 3.串扫描 (1)利用C语言编写串扫描函数
intscan_str(char*s,intlen,charc) { inti; for(i=0;i<len;i++) {
if(*s++!=c) continue; else break; }
returni; //串1与串2相等
}
返回值为c在串中的位置
!=
:循环条件、len最大比较个数
(3)利用汇编指令进行串扫描
s:串 ——〉由DI寄存器给出
len:比较长度 ——〉由CX寄存器给出
++:拷贝方向 ——〉由PSW的DF给出(CLD,STD设置) 循环条件 ——〉由指令REPNE/REPNZ给出 进一步讲,对应单元内容不相同或不为0时则重复。
重复什么?SCAS/SCASB/SCASW。 其中SCAS需要指出所扫描的串
SCASDST
而SCASB/SCASW则无需显式地给出这个串。 所比较的内容是[DI]与(AL), 或[DI]与(AX) 若不相等则继续比较。直到相等(即扫描到指定单元)为止。
结果:
(DI)相匹配字符的下一个地址;
(CX)剩下未比较的字符个数。在“12345abcde”中扫描“b”,下列程序输出
(六)转移指令
1.无条件转移指令
(1)无条件段内直接转移指令 格式:JMP标号 功能:无条件地转移到标号地址处。 例如:
NEXT:MOVAX,CX …… JMPNEXT
;转NEXT处
…… JMPOVER
;转OVER处
……
OVER:MOVAX,1
编译器根据标号与IP的相对位置,将指令翻译位跳转一定的位移量,即EBXX或EBXXX。 其中EB表示跳转,而XX或XXXX则表示要跳转的位移量。 当翻译成EBXX时,表示跳转位移为8位数,此时的跳转称为短转移。 短转移的书写格式为:
JMPSHORT
标号 执行的操作:(IP)<-(IP)+8位位移量 例如: …… JMPSHORTHELLO …… HELLO: MOVAL,3 ……
按同样的道理,当翻译成EBXXXX时,表示跳转位移为16位数,此时的跳转为近转移。 短转移的书写格式为:
JMPNEARPTR
标号 执行的操作:(IP)<-(IP)+16位位移量
对于JMPSHORTOPR和JMPNEARPTROPR,除翻译后多一个字节和少一个字节外并无多少实质的差别,因此对于段内直接转移,编程时可直接写为:
JMP标号 (2)无条件段内间接转移 格式: JMPWORDPTROPRD
功能:无条件地转移到由操作数OPRD的内容指定的去处。
OPRD可以是通用寄存器,也可以是字存储单元。
例:
JMPWORDPTR[1234H]
偏移地址为1234的内容送IP
(3)无条件段间直接(远)转移指令 格式:JMPFARPTR
标号 功能:无条件地转移到标号所对应的地址处。 标号前的符号“FARPTR”向汇编程序说明这是段间转移。
(CS)=标号所在段的段地址;
(IP)=标号在段中的偏移地址。
FARPTR指名了用标号的段地址和偏移地址去修改CS和IP.
例: C1SEGMENT …… JMPFARPTRNEXT_PROG …… C1ENDS C2SEGMENT …… NEXT_PROG: …… C2ENDS
一般不区分"JMPSHORTNEXT"与"JMPNEARPTRNEXT",因为把"JMPSHORTNEXT"处理为"JMPNEARPTRNEXT"只是增加了机器指令的长度,不会使执行结果出现错误。因此,程序中只区分"段间转移"和"段内转移"。即,出现段间转移时,使用"JMPFARPTRNEXT",否则,使用"JMPNEXT"。 (4)无条件段间间接转移指令 格式:JMPDWORDPTROPRD
功能:无条件地转移到由操作数OPRD的内容指定的去处。
OPRD必须是双字存储单元。 例如:
JMPDWORDPTR[1234H]
;双字存储单元的低字内容送IP
;双字存储单元的高字内容送CS
注意段内间接转移和段间间接转移的区别:字和双字。 2.条件转移指令
8086/8088提供了大量的条件转移指令,它们根据某标志位或某些标志位的逻辑运算来判别条件是否成立。如果成立,则转移。否则继续顺序执行。
所有条件转移都只是段内转移;条件转移不影响标志。
通常,在条件转移指令前,总有用于条件判别的有关指令。 例:下面的程序测试AX的低四位是否全为0,如果是,那么使CX=0,否则使CX=-1。
MOVCX,-1
TESTAX,0FH ;全为0是,ZF=1 JNZNZERO ;ZF=0则转移
MOVCX,0 NZERO:……
记忆技巧:
1.基于单个标志位跳转指令可直接根据标志名称记忆:JZ,JO 2.有符号数间的次序关系称为: 大于(G)、等于(E)、小于(L);
3.无符号数间的次序关系称为: 高于(A)、等于(E)、低于(B)。
对于有符号数和无符号数,使用时请注意区分。 例:实现两个无符号数(设在AX和BX中)的比较,把较大的数放在AX中,把较小的数放在BX中。
CMPAX,BX JAEOK ;无符号数比较大小转移
XCHGAX,BX OK:
……
如果要比较的两个数是有符号数,则可用下面程序片段:
CMPAX,BX JGEOK ;有符号数之间比较
XCHGAX,BX OK:
……
例如:设X、Y均为存放在X单元和Y单元中的16位操作数,先判断X>50否,如满足条件则转移到TOO-HIGH去执行,否则做X–Y,如溢出则转移到OVER去执行,否则计算|X-Y|,并把结果存入RESULT中。
MOVAX,X CMPAX,50
JGTOO-HIGH ;大于则跳转
SUBAX,Y
JOOVER ;溢出则跳转
JNSNONEG ;结果为正则跳转
NEGAX ;以上2条计算|X-Y| NONEG: MOVRESULT,AX …… TOO-HIGH: …… OVER: ……
例:假如有100个16位无符号数存放在从1234:5678H开始的内存中,现需要求它们的和。其结果用32位数存放,高位放在DX中,低位放在AX中。
MOVAX,1234H MOVDS,AX ;置段寄存器
MOVSI,5678H ;置指针初值
MOVAX,0 MOVDX,AX ;清32位累加器和
MOVCX,100 ;设置个数计数器
NEXT: ADDAX,[SI] ADCDX,0 ;32位求和
INCSI INCSI ;调整2次指针(16位,2字节)
DECCX ;调整计数器
JNZNEXT ;如不为0,则继续累加
例:在存储器中有一个首地址为ARRAY的N字数组,要求测试其中正数、0及负数的个数。正数的个数放在DI中,0的个数放在SI中,并根据N-(DI)-(SI)求得负数的个数并放在AX中,如果有负数则转移到VAL中去执行。
3.循环指令 利用条件转移指令和无条件转移指令可以实现循环。 但是,为了让循环的实现更加方便,8086/8088提供了4条用于实现循环的指令。 循环指令类似于条件转移指令,而且也采用相对转移的方式,即通过在IP上加一个地址差的方式来实现转移。 循环指令中也只有一个字节表示地址差, 所以,如果以循环指令的下一条指令作为基准,移动范围在-128至+127之间.
(1)计数循环指令LOOP
格式:LOOP标号 操作:使寄存器CX的值减1,如果结果不等于0,则转移到标号,否则顺序执行。 该指令类似于如下两条指令:DECCX JNZ标号 因此,通常在利用LOOP指令构成循环时,先要设置好计数器CX的初值,即循环次数。由于先进行CX减1,再判断结构是否为0,所以最多可循环65536次。
例: 如下面程序片段实现把从偏移1000H开始的512个字节的数据复制到从偏移3000H开始的缓冲区中(假设在当前数据段中进行移动)。
MOVSI,1000H;置源指针
MOVDI,3000H;置目标指针
MOVCX,512 ;置计数初值
NEXT: MOVAL,[SI] MOV[DI],AL INCSI INCDI LOOPNEXT ;控制循环
……
(2)等于/全零循环指令LOOPE/LOOPZ
等于/全零循环指令有2个助记符,格式如下:
LOOPE标号 或 LOOPZ标号 操作:使寄存器CX的值减1,当CX不等于0且ZF为1时(相等),进行循环,否则退出循环并顺序执行后续语句。
ZF标志从哪里来?通过CMP、DEC、TEST、ADD、SUB等运算指令设置。 例:在字符串中查找第一个非‘A’字符。设字符串长已保存在CX中,并且DS:DI指向字符串。如果找到,那么使BX指向该非‘A’字符,如果找补到,那么使BX=-1。
(3)不等于/非全零循环指令LOOPNE/LOOPNZ
不等于/非全零循环指令有2个助记符,格式如下:
LOOPNE标号 或 LOOPNZ标号 操作:使寄存器CX的值减1,当CX不等于0且ZF为0时(不相等),进行循环,否则退出循环并顺序执行后续语句。
ZF标志从哪里来?通过CMP、DEC、TEST、ADD、SUB等运算指令设置。 (4)跳转指令JCXZ JCXZ也可以认为是条件跳转指令。格式如下:
JCXZ标号 该指令实现当CX的值等于0时转移到标号,否则顺序执行。
通常该指令用在循环开始前,以便根据需要判断是否跳过循环体。
例如:有一长度为L的字符串,存储于首地址为TABLE的存储器中。要求在字符串中查找“空格”字符,找到则继续执行,如未找到则转到NOT-FOUND去执行
MOVCX,L MOVSI,-1 MOVAL,20H;空格字符的ASCII码
NEXT: INCSI
CMPAL,TABLE[SI];若相等,则ZF=1
LOOPNENEXT ;ZF=0且(CX)不等于0则循环
JNZNOT-FOUND ;ZF=0则转移。ZF=0,说明循环
;体不是因为相等而退出,而是因为(CX)为0了。
…… NOT-FOUND:…….
例如:若自BLOCK开始的内存缓冲区有100个字节带符号数,要找出其中最大值,把它存放到MAX单元中。
MOVBX,OFFSETBLOCK MOVAX,[BX] INCBX MOVCX,99
AGAIN:
CMPAX,[BX]
JGNEXT MOVAX,[BX] NEXT: INCBX
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 古玩定金合同范本
- 住房修建合同范本
- 包装产品设计合同三篇
- 独立中介合同范本
- 采购合同范本全文
- 广告经营合同范本
- 隧道劳务合同范本
- 铲车的合同范本
- 公寓合租合同范本
- 2024至2030年中国鸭里脊数据监测研究报告
- 第五节 错觉课件
- 2024-2030年中国水煤浆行业发展规模及投资可行性分析报告
- 2024-2030年陕西省煤炭行业市场发展分析及发展前景预测研究报告
- 【课件】Unit+3+SectionB+1a-2b+课件人教版英语七年级上册
- 干部人事档案任前审核登记表范表
- 期中阶段测试卷(六)-2024-2025学年语文三年级上册统编版
- 北京市昌平区2023-2024学年高二上学期期末质量抽测试题 政治 含答案
- 第7课《不甘屈辱奋勇抗争》(第2课时)(教学设计)-部编版道德与法治五年级下册
- 中国脑出血诊治指南
- 2024-2030年中国融资租赁行业市场发展分析及前景趋势与投资前景研究报告
- 吉安市市直事业单位选调工作人员真题
评论
0/150
提交评论