第二节 指令系统

8086/8088共有92条指令,正确理解和掌握每一条指令的功能和格式,是汇编语言程序设计的基础。

一、指令系统概述

(一)指令分类

92条指令构成了8086/8088指令系统,它们可分为六大类。

(1)传送类指令(Transfer instructions)。

(2)算术运算类指令(Arithmetic instructions)。

(3)位操作类指令(Bit manipulation instructions)。

(4)串操作类指令(String instructions)。

(5)程序转移类指令(Program transfer instructions)。

(6)处理器控制类指令(Processor Control instructions)。

(二)指令格式

8086/8088指令系统中的指令有3种格式。

(1)双操作数指令:OPR DEST,SRC

(2)单操作数指令:OPR DEST

(3)无操作数指令:OPR

其中,OPR是指令操作符,也称为指令助记符,它表示指令要执行何种操作。双操作数指令指定两个操作数,第一个为目的操作数,第二个为源操作数,两操作数之间要用逗号“,”分隔,它们的位置不能互换,操作的结果一般在目的操作数中。因此,目的操作数不能是常数,而只能是寄存器操作数或存储器操作数。语句执行后,目的操作数原来的内容将发生改变,而源操作数的内容不会改变。

单操作数指令只需要一个操作数,它或是源操作数(SRC),或是目的操作数(DEST)。

对于无操作数指令,虽然指令本身未指明操作数是什么、在哪里,但指令却隐含规定了操作数及存放地点。

(三)指令规则

8086/8088指令在使用时有较严格的规定,要正确地掌握和运用这些指令,首先要准确地掌握这些规则。8086/8088汇编语言指令共同遵守如下规则。

(1)规则1:除通用数据传送指令(MOV、PUSH、POP)之外,段寄存器不允许作为操作数。

(2)规则2:段寄存器不能直接用立即数赋值。

(3)规则3:代码段寄存器CS和立即数不能作为目的操作数。

(4)规则4:指令中两个操作数不能同时为段寄存器。

(5)规则5:指令中两个操作数不能同时为存储器操作数(串指令除处)。

(6)规则6:指令中两个操作数的类型(字节类型或字类型等)必须一致。

(7)规则7:指令中至少要有一个操作数的类型是明确的,否则须用操作符PTR临时指定操作数类型(见第四章)。

下面介绍8086/8088指令。

二、传送类指令

传送类指令.mp4

传送类指令共有12条,包括通用数据传送指令(MOV、PUSH、POP)、交换指令(XCHG)、查表指令(XLAT)、地址传送指令(LEA、LDS、LES)和标志传送指令(PUSHT、POPT、LAHF、SAHF)。它们可以将各种类型的操作数从源传送到目的,其传送途径见图3-1。图中实线表示合法传送途径,虚线为非法传送途径。所有的传送类指令对标志位均无影响。

图3-1 数据的传送途径

(一)通用数据传送指令

这种指令共有3条。

1. 传送指令(Mov)

格式:MOV DEST,SRC

功能:把源操作数的内容传送给目的操作数,即DEST←SRC。

说明:当MOV指令执行完后,源操作数和目的操作数都将有相同的内容,目的操作数原有的内容消失。MOV指令可以进行字节数据传送,也可进行字数据的传送。

例:

而下面的指令是非法的(参见指令规则):

2. 进栈指令(Push Word Onto Stack)

格式:PUSH SRC

操作:(1)堆栈指针减2指向新的栈顶,SP←SP-2。

(2)将给定的操作数放入SP指示的字单元中。

说明:进栈指令的操作数是一个16位的寄存器操作数或存储器操作数,不允许是立即数。

例:

3. 出栈指令(Pop Word Off Stack Into Destination)

格式:POP DEST

操作:(1)将栈顶的字数据送入操作数DEST中,DEST←(SP+1,SP)。

(2)堆栈指针加2指向新栈顶,SP←SP+2。

例:

通用数据传送指令的通用性在于它适合所有的操作数,比如可使用段寄存器作为操作数,而除了这3条通用数据传送指令之外,任何8088指令都不能在指令中出现段寄存器(见指令规则1)。

(二)交换指令(Exchange)

格式:XCHG DEST,SRC

操作:将两个操作数的内容互换,即(DEST)←→(SRC)。

例:

若进行两个内存单元D1_BYTE和D2_BYTE之间的数据交换,可用如下3条指令实现:

     MOV   AL,D1_BYTE
     XCHG  AL,D2_BYTE
     XCHG  AL,D1_BYTE

下面的指令是非法的(参见指令规则):

(三)查表指令

格式:XLAT

功能:将数据段(DS)中偏移地址为BX+AL的内存字节单元的内容送入AL中,即AL←(BX+AL)。

说明:XLAT指令用于查表。表的开始地址即表头地址由BX给出。AL中的原始值是要查找的表中元素的地址位移量。

例如:如图3-2所示,在内存符号地址TABLE开始有一个0~9的数的平方表。假如要查5的平方值,把被查数5放入AL中(这正好就是它本身的平方值在表中存放的位移量),将表头地址送入BX中(MOV BX,OFFSET TABLE),使用XLAT指令后在AL中就能得到5的平方值。

图3-2 平方查表示意

(四)地址传送指令

这种指令共3条,它们不是传送存储器操作数的内容,而是传送它的地址(偏移量,段基值)。

1. 装入有效地址(Load Effective Address)

格式:LEA DEST,SRC

功能:把源操作数的偏移量(即有效地址EA)送给目的操作数的通用寄存器。本指令中SRC必须是一个存储器操作数,而DEST一定是16位通用寄存器。

例:

2. 装入地址指针(Load Address of Point)

地址指针的值是由16位段基值和16位偏移量两部分构成的,装入地址指针指令能用一条指令实现将存放在内存中的地址指针值的段基值送入段寄存器,同时将偏移量部分送入指令规定的寄存器中。

格式:(1)LDS DEST,SRC

(2)LES DEST,SRC

功能:将双字长存储器操作数SRC的低地址字单元内容送入指定的寄存器DEST中,而将双字长存储器操作数SRC的高地址字单元内容送入DS(LDS)或ES(LES)。

说明:指令的目的操作数(DEST)要存放地址指针的偏移值部分,因此,必须是一个16位通用寄存器,而SRC一定是存储器操作数。

例如,设SI间址寄存器所指的内存单元存放的数据如图3-3所示,若有下面指令:

图3-3 LDS指令的传送

     LDS  BX,[SI]

则该指令执行后,DS内容为9010H,BX内容为302FH。

(五)标志传送指令(Flags Transfer)

8086/8088设计了4条指令专门用于标志寄存器的存取操作。它们都是无操作数指令。

1. 取标志寄存器

格式:LAHF

功能:把标志寄存器的低8位传送给AH寄存器。

2. 存储标志寄存器

格式:SAHF

功能:把寄存器AH中的第7、6、4、2、0位的内容分别送入标志寄存器SF、ZF、AF、PF和CF各标志位。标志寄存器OF、DF、IF和TF各位均不受影响。

3. 标志进栈

格式:PUSHF

功能:首先把堆栈指针SP减2,然后将16位标志寄存器的全部内容(含所有标志位)送入SP指向的堆栈顶部。标志寄存器中各标志位本身不受影响。

4. 标志出栈

格式:POPF

功能:首先将现行堆栈顶部(由SP决定)的一个字的内容送入标志寄存器,然后SP+2。标志寄存器中各标志位的状态,由从堆栈中弹出字的相应位的内容所决定。

标志寄存器中只有少数几个标志位(如CF、DF、IF)有专门的指令进行置0或置1操作,其余大部分标志位都没有指令直接对它们进行设置或修改。例如要修改SF,那么可首先用LAHF指令把含有SF标志位的标志寄存器低8位送入AH,然后对AH的第7位(对应SF位)进行修改或设置,再用SAHF指令送回标志寄存器。

三、算术运算类指令

算术运算类指令.mp4

8086/8088的算术运算指令提供加、减、乘、除四类运算,可对4种数据进行处理。这4种数据如下。

(1)无符号二进制数。

(2)带符号二进制数。

(3)无符号组合十进制数(组合BCD码)。

(4)无符号非组合十进制数(非组合BCD码)。

(一)二进制加法运算指令

二进制加法指令有3条,指令格式和功能如下。

1. 加法指令

格式:ADD DEST,SCR

功能:将源操作数SCR和目的操作数DEST相加,结果存入DEST中,即DEST←DEST+SCR。

说明:加法指令可以进行字节或字的加法,其结果放在目的操作数中,源操作数原有的内容不变(对任何指令都是如此)。

例:

     ADD  AX,X
     ADD  AL,0A4H
2. 带进位加指令

格式:ADC DEST,SCR

功能:将源操作数SCR、目的操作数DEST及进位标志CF位相加,结果存入DEST中,即DEST←DEST+SCR+CF。

说明:ADC指令主要用于大于16位(多字节)数的加法中。例如,有一个32位二进制数已存放在AX(高16位)和BX(低16位)中,现要加上常数208A9F88H,可用下面两条指令来实现:

     ADD  BX,9F88H
     ADC  AX,208AH

其中,第一条指令把低16位常数9F88H加在BX中,若它们相加高16位有进位时,则把进位记录在CF中。在第二条指令完成高16位加时,用ADC指令同时把低16位的进位一起加上。

3. 加1指令

格式:INC DEST

功能:将目的操作数DEST自身加1,结果存入DEST中,即DEST←DEST+1。

说明:INC指令主要用于某些计数器的计数和地址指针值的修改。

例:

     INC  SI  ;SI←SI+1

注意:加法指令会按其执行结果设置6个状态标志的状态,但INC指令对进位标志CF无影响。

(二)二进制减法运算指令

1. 减法指令

格式:SUB DEST,SRC

功能:将目的操作数DEST内容减去源操作数SRC内容,结果送入DEST中,即DEST←DEST-SRC。

2. 带借位减法指令

格式:SBB DEST,SRC

功能:将目的操作数DEST内容减去源操作数SRC内容及CF位,结果送入DEST中,即DEST←DEST-SRC-CF。

说明:SBB指令在使用上类似于ADC指令,主要用于大于16位的多精度数的减法,把低位部分相减的借位引入高位部分的减法中。

3. 减1指令

格式:DEC DEST

功能:将目的操作数DEST内容减1,结果送入DEST中,即DEST←DEST-1。

说明:DEC指令使用上类似于INC指令,主要用于计数和修改地址指针,但方向与INC指令相反。DEC操作不影响进位标志CF。

4. 比较指令

格式:CMP DEST,SRC

功能:目的操作数DEST减去源操作数SRC,即DEST←DEST-SRC。

说明:CMP指令将两个操作数相减,但相减的结果并不保留,两个操作数都保持原值不变,只是将相减结果的特征反映在各个状态标志位上。比如当CMP指令执行后,如果标志位ZF=1,说明被比较的两数相等,可以在CMP指令后,用单标志判断转移指令或条件判断转移指令来确定比较的结果(大于、小于、等于)。

5. 取补指令

格式:NEG DEST

功能:零减去目的操作数DEST,结果存入目的操作数DEST,即DEST←0-DEST。

说明:NEG指令是求操作数的负数,即改变操作数的符号,这对带符号数来说就是求其补码。因此NEG也叫取补指令。NEG对标志位影响有特殊规定,如果被取补的操作数非0,NEG操作后,CF置1,否则CF=0。

(三)二进制乘法运算指令

1. 无符号数乘法指令

格式:MUL SRC

功能:若SRC为字节长度,则AX←AL×SRC;若SRC为字长度,则DX:AX←AX×SRC。

说明:乘法指令格式中只出现源操作数,根据这个操作数的类型(字节类型或字类型)决定是8位乘还是16位乘。因此,SRC不能是立即数(立即数无类型属性),而目的操作数(被乘数)隐含约定为累加器AL(8位乘)或AX(16位乘),运算的结果约定在AX中(8位乘法的积)或DX:AX中(16位乘法的积),如图3-4所示。

图3-4 乘法指令操作示意

2. 带符号数乘法指令

格式:IMUL SRC

功能:功能同MUL指令

说明:乘法指令对标志的影响有特殊规定,它只影响标志位CF和OF。对于MUL,如果乘积的高半部(8位乘时为AH,16位乘时为DX)为零,CF=0,OF=0;否则CF=1,OF=1(表示AH或DX中有乘积的有效数字)。对于IMUL,若积的高半部是低半部的符号扩展,则CF=0,OF=0;否则CF和OF均为1。

(四)二进制除法指令

二进制除法运算指令包括无符号数除法(DIV)和带符号数除法(IDIV)。对带符号数来说,还有两条符号扩展指令(CBW、CDQ)。

1. 无符号数除法指令

格式:DIV SRC

功能:若SRC为字数据,则AX/SRC,AL←商,AH←余数;若SRC为字数据,则DX:AX/SRC,AX←商,DX←余数。

2. 带符号数除法指令

格式:IDIV SRC

功能:同DIV指令。

说明:同乘法指令类似,除法指令中的操作数SRC为除数,它不能是立即数。目的操作数(被除数)也有两种情况,当除数为8位时被除数隐含为AX,运算结果商约定在AL中,余数约定在AH中;当除数为16位时,被除数隐含在DX:AX,运算结果约定在AX中,余数在DX中,如图3-5所示。

图3-5 除法指令操作示意

注意:

(1)除法指令对标志位的影响无意义。

(2)除数必须足够大,使得商值小于等于8位或16位数表示的范围;否则,将产生除法错误。

3. 字节扩展指令

格式:CBW

功能:对AL中的带符号数进行符号扩展。若AL<0,AH=0FFH,否则AH=0。

(五)十进制算术运算指令

大家知道,计算机只能处理二进制信息,但在实际的生产和生活中,人们习惯使用十进制数。因此,需要计算机处理的原始数据大部分是十进制数据。人们希望计算机能接收这些十进制数,并将处理的结果以十进制形式输出。这时从外部来看,好像计算机在进行十进制数运算一样。

每一位十进制数在计算机内部,通常是用4位二进制数表示的,它是十进制数的二进制编码。8086/8088 CPU实现十进制运算的方法是仍将这些十进制数(BCD码)看作二进制数,使用二进制加、减、乘、除指令进行运算,不过在运算后(或前)用调整指令进行调整以得到十进制(BCD码)结果。故此,针对非组合和组合BCD码,8086/8088提供了6条算术运算相应的BCD码调整指令。

1. 非组合十进制调整指令

(1)加法调整指令(ASCII Adjust for Addition)。

格式:AAA

功能:若AL中的低4位值大于9或AF=1,则将AL加6和AH加1,并将AF和CF置1,然后将AL的高4位清0;否则只进行清AL高4位操作。

受影响的状态标志位:AF、CF(OF、ZF和PF的状态不确定)。

(2)减法调整指令(ASCII Adjust for Subtraction)。

格式:AAS

功能:如果AL中的低4位大于9或AF=1,那么就将AL减6且AH减1,并将AF和CF置1,然后将AL的高4位清0;否则只进行清AL高4位操作。

受影响的状态标志位:AF、CF(OF、SF、ZF和PF的状态不确定)。

(3)乘法调整指令(ASCII Adjust for Multiply)。

格式:AAM

功能:将AL中的内容除以10,商送入AH中,余数送入AL中。

受影响的状态标志位:SF、ZF、PF(OF、AF、CF状态不确定)

说明:AAM指令将两个有效的非组合十进制数相乘后得到的乘积调整为一个有效的非组合十进制数,AAM指令执行后被调整字节的高4位为0。

(4)除法调整指令(ASCII Adjust for Division)。

格式:AAD

功能:将AH中的内容乘以10后与AL相加,结果存到AL中,然后将AH清0。

受影响的状态标志位:SF、ZF、PF(OF、AF、CF状态不确定)。

说明:AAD指令在两个有效的非组合十进制数做除法之前调整AL中的内容,以使除法得到的商数为一个有效的非组合十进制数。为了使跟在其后的DIV指令能产生一个正确的结果,AH必须为0。除法指令执行后,商存放在AL中,余数存放在AH中,它们的高4位都为0。

2. 组合十进制调整指令

(1)加法调整指令(Decimal Adjust for Addition)。

格式:DAA

功能:如果AL中的低4位大于9或AF=1,那么就将AL加6,并将AF置1;如果AL的高4位大于9或CF=1,则将60H加到AL中,并将CF置1。

受影响的状态标志位:OF、SF、ZF、AF、PF、CF。

(2)减法调整指令(Decimal Adjust for Subtraction)。

格式:DAS

功能:如果AL中的低4位大于9或AF=1,那么就将AL减6,并将AF置1;如果AL的高4位大于9或CF=1,则从AL中减去60H,并将CF置1。

受影响的状态标志位:SF、ZF、AF、PF、CF(OF不确定)。

总结:

所谓十进制算术运算(BCD码运算)指令,就是在二进制算术运算指令之后加上一个相应的调整指令(除法指令是先调整后跟除法指令),因此,可以将十进制算术运算指令看成一个由两条指令构成的复合指令,例如,组合十进制加法指令为:

注意:调整指令仅对累加器AL的内容进行调整,因此,在进行十进制算术运算时,目的操作数必须使用累加器。

四、位操作指令

位操作指令是指按位进行操作的指令,包括逻辑运算指令、移位和循环移位指令两种。

(一)逻辑运算指令(logical)

位操作指令.mp4

共有5条逻辑运算指令,它们的指令格式和功能如下。

1. 逻辑“与”指令

格式:AND DEST,SRC

功能:DEST←DEST∧SRC;CF=0,OF=0。

2. 逻辑“或”指令

格式:OR DEST,SRC

功能:DEST←DEST∨SRC;CF=0,OF=0。

3. 逻辑“异或”指令

格式:XOR DEST,SRC

功能:DEST←DEST⊕SRC;CF=0。OF=0。

4. 逻辑“非”指令

格式:NOT DEST

功能:DEST←DEST。

5. 测试指令

格式:TEST DEST,SRC

功能:DEST∧SRC。

总结:

(1)逻辑操作指令对标志位的影响有特殊规定。

① NOT指令对标志位没有影响。

② 执行除NOT指令之外的逻辑指令后,OF和CF两个标志都被清0,而AF状态不确定,其他标志反映操作结果的状态。

(2)TEST指令对两个操作数进行“与”操作,但不保留“与”的结果,只是通过标志状态的判断,得出测试结果。主要用于测试一个操作数(目的操作数)某一位或几位的状态。

(3)逻辑指令主要用于字节或字中某些位的组合、分离或位设置等。

例:

(二)移位和循环移位指令

移位和循环移位指令共有8条,它们的指令格式和操作如表3-4所示。

表3-4 移位和循环移位指令

说明:

(1)目的操作数dest可以是通用寄存器或存储器操作数,cnt为移位次数,可以是1,或由CL指出(移位次数大于1时必须用CL给出移位次数),位移结束后CL值不变。

(2) CF的值总是最后一次被移入的值。

(3)移位指令影响标志位CF、OF、SF、ZF。而循环移位指令仅影响CF和OF位。

(4)对OF影响的规定是:在移动1位的情况下,如果移位后操作数的最高位改变了,OF就被置1,否则OF被置0。若移位次数大于1,那么OF不确定。

五、转移类指令

转移类指令.mp4

在8086/8088汇编语言程序中,指令执行的顺序由代码段寄存器CS和指令指针IP所确定,在正常情况下,程序总是顺序执行的。CPU每执行完一条指令,就自动修改IP的值使之指向下一条指令。转移指令可以实现程序流向的控制和转移,这是通过改变CS和IP值实现的。若转移在同一段内进行(段内转移),就只需要修改IP值;若是在两个段之间进行转移(段间转移),则CS和IP都需要修改。

根据转移的范围将转移分为3类。

(1)远转移(段间转移):转移的目标地址为32位。可以实现一个段到任意其他代码段的转移。

(2)近转移(段内转移):转移的目标地址为16位。转移的距离限定在当前段内,最大64KB。

(3)短转移:转移的目标地址为8位。转移范围限定在从转移指令的下一条指令算起的-128~+127个字节的地址空间以内。

转移类指令包括无条件转移指令、条件转移指令、循环控制指令、调用/返回指令、中断指令等。本节只介绍前3种,后两种在相关章节中叙述。

(一)无条件转移指令

无条件转移指令仅有一条,它可以实现远转移、近转移或短转移。格式:JMP targ

功能:(1)段内转移:IP←目标的偏移地址。

(2)段间转移:IP←目标的偏移地址,CS←目标所处代码段基址。

说明:JMP指令使程序无条件地转移到目标targ指明的地址处执行。根据targ的类型会自动产生一个远转移、近转移或短转移指令。指令中的targ可以是标号、寄存器或存储器操作数,JMP对标志位无影响。

例:

(二)条件转移指令

条件转移指令是根据CPU中状态标志位当前的状态决定程序执行的流程,既可能产生程序转移,也可能不产生程序转移。条件转移指令是以对不同的状态标志的测试为条件,如果条件成立,则控制转移到指令中所给出的转移目标,如果条件不成立,程序将顺序执行。

条件转移指令共有18条,它们都是两个字节长的指令,其中一个字节为操作码,另一个字节为转移目标的偏移量(本指令的下条指令与目标的相对字节距离)。由于相对转移目标仅8位长,因此,所有的条件转移指令都仅能实现短转移。

条件转移指令见表3-5,这些指令对标志位无影响。条件转移指令中的targ是要转向的指令语句标号,经汇编产生一个相对位移量,是一个8位带符号数。

表3-5 条件转移指令

条件转移指令一般用在算术运算、逻辑运算,或某些比较、测试指令之后,根据这些指令操作后的结果(反映在各状态标志上)判断转移。

(三)循环控制指令

在转移类指令中,有3条循环控制指令,用来支持循环结构程序设计。它们和条件转移指令相同,仅能实现短转移。这3条指令均约定用CX作为循环次数计数器,因此,这种指令只能用在循环次数已知的循环程序中。在执行循环控制指令时,自动对CX进行减1操作,并自动判断CX是否减为0,这样,用循环控制指令比用条件转移指令来控制循环更简洁、方便。

1. 无条件循环控制指令

格式:LOOP targ

功能:若CX-1≠0则转移,否则退出循环。相当于两条指令:

     DEC  CX
     JNZ  targ

该指令使循环体无条件循环CX中指定的次数。

2. 相等循环控制指令

格式:LOOPZ targ 或 LOOPE targ

功能:若CX-1≠0(规定的循环次数没完)且ZF=1(比较相等)则转移,否则退出循环。

3. 不等循环控制指令

格式:LOOPNZ targ 或 LOOPNE targ

功能:若CX-1≠0(规定的循环次数没完)且ZF=0(比较不等)则转移,否则退出循环。

另外还有一条JCXZ指令也可用于循环控制。

格式:JCXZ targ

功能:若CX=0则转移,否则执行后续指令。

六、串操作指令

串操作指令.mp4

用字节或字组成的一组数据称为数据串。组成数据串的字节或字称为数据串元素。如字符串‘abcdef’是一个字节数据串,串中每一个字符的ASCII码构成了该数据串的元素。

对数据串的传送、比较、搜索、存取等操作是非常典型、常用的操作。为此,汇编语言设计了5条专门用于上述操作的串指令。并且设计了3个重复前缀,它们加在串操作指令前,使得用一条指令就可完成一个循环程序的功能,而且不用考虑指针如何移动、循环如何控制等问题,极大地方便了程序设计。

(一)串操作指令的隐含规定

5条串操作指令隐含地使用了相同的寄存器、标志位和符号。隐含规定如下。

(1)源串指针:DS:SI,目的串指针:ES:DI。

(2)重复次数计数器:CX(加重复前缀时)。

(3)操作方向:DF=0,正向(SI、DI自动增量修改);DF=1,负向(SI、DI自动减量修改)。操作方向可用CLD和STD指令设置。

(4)指令SCAS、LODS、STOS约定累加器为一个操作数。

(二)串操作指令格式与功能

串操作指令可以实现字节和字串的操作,指令分别如下。

1. 串传送指令

(1)MOVSB ;将源串一字节传送到目的串,并自动修改指针值。

;[ES:DI]←[DS:SI],SI←SI±1,DI←DI±1

(2)MOVSW ;将源串一字传送到目的串,并自动修改指针值。

;[ES:DI]←[DS:SI],SI←SI±2,DI←DI±2

2. 串比较指令

(1)CMPSB ;源串一字节与目的串一字节相减比较,并自动修改指针值。

;[DS:SI]-[ES:DI],SI←SI±1,DI←DI±1

(2)CMPSW ;源串一字与目的串一字相减比较,并自动修改指针值。

;[DS:SI]-[ES:DI],SI←SI±2,DI←DI±2

3. 串搜索指令

(1)SCASB ;将AL内容与目的串内容进行比较,并自动修改指针值。

;AL- [ES:DI], DI←DI±1

(2)SCASW ;AX- [ES:DI],DI←DI±2

4. 从源串中取数指令

(1)LODSB ;AL←[DS:SI], SI←SI±1

(2)LODSW ;AX←[DS:SI], SI←SI±2

5. 往目的串中存数指令

(1)STOSB ;[ES:DI] ←AL,DI←DI±1

(2)STOSW ;[ES:DI] ←AX,DI←DI±2

注意:

(1)修改地址指针时加减由DF状态决定。DF=0时增量修改,DF=1时减量修改。

(2)5条串操作指令都有另一种带操作数的格式:

MOVS dest,src

CMPS dest,src

SCAS dest

LODS src

STOS dest

因上述格式不常用,所以在指令格式中未列出。

(三)串操作的重复前缀

串操作指令与普通指令相比,只是多了一个自动修改地址指针的功能。加入重复前缀,才使得串操作指令得以重复执行。

1. 无条件重复前缀指令

格式:REP

功能:使REP后的指令无条件重复CX值指定的次数。用于MOVS、STOS指令前。

2. 相等重复前缀指令

格式:REPZ/REPE

功能:当CX≠0(规定的重复次数没完)同时ZF=1(比较相等)时,重复执行该前缀后的指令,否则,终止(CX已为0)或中止(CX≠0,但ZF=0)重复。该前缀只能用于CMPS和SCAS前,在两个数据串中找出不同的元素。

3. 不相等重复前缀指令

格式:REPNZ/REPNE

功能:当CX≠0(规定的重复次数没完)同时ZF=0(比较不相等)时,重复执行该前缀后的指令;否则,终止(CX已为0)或中止(CX≠0,但ZF=1)重复。该前缀只能用于CMPS和SCAS前,在两个数据串中找出相同的元素。

注意:

(1)CX是否为0的判断(即重复操作是否完成的检测)是在串操作之前进行的,因此,若CX的初值为0,则串操作一次也不会执行。

(2)对比较和搜索的串操作结束,有两种可能:一种是重复了规定的次数(CX已为0),也没有找到要找的元素;另一种是中途或最后找到了要找的元素。这两种情况可通过对标志ZF的判断确定:如果ZF的状态和重复的条件相同(不相等重复时ZF=0,相等重复时ZF=1),则为第一种情况,否则为第二种情况。

(3)操作结束后,SI、DI中为下一个元素的偏移地址,其方向由DF确定。

下面通过例子体会一下串操作指令的应用。

【例3.1】 将以SBUF为首址的200字节的数据块传送到DBUF开始的区域,可用以下程序段实现:

     CLD
     LEA  SI,SBUF
     LEA  DI,DBUF
     MOV  CX,200
     REP  MOVSB

【例3.2】 STRING为一个30字节长的字符串,查找该串中最后一个字母‘B’,若找到将其地址存入BX中,否则将0送入BX。

这个问题可以使用带不相等重复前缀的串搜索指令完成。要查找串中最后一个字母‘B’,可从后面开始反向查找。程序段如下:

七、处理器控制类指令

处理器控制类指令.mp4

这一类指令主要包括以下3种。

(一)标志位操作指令

它们均是无操作数指令,即它们的操作数隐含在标志寄存器中某些标志位上。能直接操作(修改)的标志位有CF、IF和DF。

(1)清除进位标志指令: CLC ;置CF=0

(2)进位标志置位指令: STC ;置CF=1

(3)进位标志取反指令: CMC ;CF取反

(4)清除方向标志指令: CLD ;置DF=0(正向)

(5)方向标志置位指令: STD ;置DF=1(反向)

(6)清除中断标志(关中断)指令: CLI ;置IF=0

(7)中断标志置位(开中断)指令: STI ;置IF=1

注意:上述7条指令功能是把对应的标志位置0、置1或取反而不改变其他标志位。

(二)空操作指令

格式:NOP

功能:这条指令使CPU执行一次空操作,不影响任何寄存器、存储单元和标志位,仅占据CPU的3个时钟周期。在软件延时程序中,可用NOP指令作少量的延时调整。

(三)外部同步指令

这方面指令有WAIT、ESC、LOCK、HLT等。这些指令的执行涉及其他知识,故这里不讨论这些指令。在实际应用中,需要用这些指令时,可查阅有关资料。