这条指令和PUSHF指令一起可以保存和恢复标志寄存器的内容,即保存和恢复各标志的值。另外,这两条指令也可以用来改变追踪标志TF。 (2)标志位操作指令 ①清进位标志指令CLC 格式:CLC
该指令使进位标志为0。也就是说CF=0。 ②置进位标志指令STC 格式:STC
该指令使进位标志为1。也就是说CF=1。 ③进位标志取反指令CMC 格式:CMC
该指令使进位标志取反。如CF为1,则使CF为0;如CF为0,则CF为1。 ④清方向标志CLD 格式:CLD
该条指令使方向标志DF为0。从而在执行串操作指令时,使地址按递增方式变化。 ⑤置方向标志STD 格式:STD
该条指令使方向标志DF为1。从而在执行串操作指令时,使地址按递减方式变化。 ⑥清中断允许标志CLI 格式:CLI
该条指令使中断允许标志IF为0。于是CPU就不响应来自外部装置的可屏蔽中断。但对不可屏蔽中断和内容中断都没有影响。 ⑦置中断允许标志STI 格式:STI
该条指令使中断允许标志IF为1,则CPU可以响应可屏蔽中断。 (二)加减运算指令 1.加法指令ADD
格式:ADD OPRD1,OPRD2
执行的操作:(OPRD1)←(OPRD1)+(OPRD2) 例如:MOV AX,7896H ;AX=7896H
即 AH=78H AL=96H ;各标志位保持不变
ADD AL,AH ;AL=AL+AH=96H+78H(=10EH)=0EH 前面的1给了进位标志CF。
即 AH=78H, AX=780EH
CF=1 PF=0 AF=0 ZF=0 SF=0 OF=0 例如:ADD DX,0F0F0H 执行前(DX)=4652H
执行后(DX)=4652H+F0F0H(=13742H)=3742H 前面的1给了进位标志CF。 ZF=0 SF=0 CF=1 OF=0
这里4的二进制码是0100,F是1111,一个正数一个负数相加肯定OF是0。 例如:ADD AX,4321 执行前(AX)=62A0H
执行后(AX)=62A0+4321=A5C1H 这里要注意,A的二进制数是1010,最高有效位为1,所以SF为1。
两个正数相加,结果为负的就溢出;两个负数相加,结果为正的就溢出。 SF=1 ZF=0 CF=0 OF=1
这里6的二进制码是0110,而4的二进制码是0100,两个正数相加,结果A为1010为负,所以OF为1。
从上面例子可看出:加法指令影响标志位。
OF位根据操作数的符号及其变化情况来设置:若两个操作数的符号相同而结果的符号与之相反时OF=1,否则OF=0。
CF位可以用来表示无符号数的溢出。由于无符号数的最高有效位只有数值意义而无符号意义,所以从该位产生的进位应该是结果的实际进位值,但在有限数的范围内就说明了结果。 2.带进位加指令ADC 格式:ADC OPRD1,OPRD2
执行的操作:(OPRD1)←(OPRD1)+(OPRD2)+(CF)
例如:下列指令序列执行两个双精度(32位)的加法。设目的操作数放在DX和AX寄存器中,其中DX存放高位字,源操作数存放在BX、CX中,其中BX存放高位字。(双精度的数高位和高位相加,低位和低位相加,首先加低位。)
如指令执行前:(DX)=0002H (AX)=0F365H (BX)=0005H (CX)=0E024H 指令序列为:ADD AX,CX ADC DX,BX 执行第一条指令后:
(AX)=AX+CX=F365+E024)=1D389)=D389H SF=1 ZF=0 CF=1 OF=0
这里F的二进制是1111,E的二进制是1110,得出的D是1101。所以OF为0。(8以上全是负的,
8以下全是正的) 执行第二条指令后:
(DX)=DX+BX+CF=0002+0005+0001=0008H SF=0 ZF=0 CF=0 OF=0
则该指令序列执行完后:(DX)=0008H (AX)=D389H 从上面的例子可以看出:
为实现双精度加法,必须用两条指令分别完成低位字和高位字的加法,而且在高位字相加时,应该使用ADC指令以便把前一条ADD指令作低位字加法所产生的进位值加入高位字之内。另外,带符号的双精度数的溢出,应该根据ADC指令的OF位来判断,而作低位加法用的ADD指令的溢出是无意义的。此指令影响标志位。 3.加1指令INC 格式:INC OPRD
这条指令完成对操作数OPRD加1,然后把结果送回OPRD,即: (OPRD)←(OPRD)+1
操作数OPRD可以是通用寄存器,也可以是存储单元。这条指令执行的结果影响标志ZF、SF、OF、PF和AF,但它不影响CF。 该指令主要用于调整地址指针和计数器。
例如:写出把首地址为BLOCK的子数组的第6个字送到DX寄存器的指令。 要求使用以下几种寻址方式: (1)寄存器间接寻址
MOV BX,OFFSET BLOCK ;首先把BLOCK里的偏移地址送给BX ,这里也可以用LEA BX,BLOCK
ADD BX,000AH MOV DS,[BX] (2)寄存器相对寻址 MOV BX,OFFSET BLOCK MOV DX,[BX]000AH] 4.减法指令SUB
格式:SUB OPRD1,OPRD2
执行的操作:(OPRD1)←(OPRD1)-(OPRD2) 例如:SUB [SI+14H],0136H
指令执行前(DS)=3000H, (SI)=0040H, (30054H)=4336
物理地址=DS+SI+14H=30000+0040+0014=30054H SUB(30054H)=4336-0136=4200H
指令执行后(30054H)=4200H SF=0 ZF=0 CF=0 OF=0 例如:SUB DH,[BP+4]
指令执行前(DH)=41H, (SS)=0000H, (BP)=00E4H, (000E8H)=5AH SS:BP=00000+00E4+4=000E8 =5AH SIB DH-BP=41H-5AH=E7H 指令执行后(DH)=0E7H
SF=1 ZF=0 CF=1 OF=0
此指令影响标志位CF位说明无符号数想减的溢出,同时它又是被减数的最高有效位向高位的借位值。OF位则说明带符号数的溢出。减法的OF位的设置方法为:若两个数的符号相反,而结果的符号与减数相同则OF=1。说明结果是错误的。 5.带借位减指令SBB 格式:SBB OPRD1,OPRD2
执行的操作:(OPRD1)←(OPRD1)-(OPRD2)-CF 例如:SBB AL,DL SBB DX,AX
该指令主要用于多字节数相减的场合。 6.减1指令DEC 格式:DEC OPRD
执行的操作:(OPRD)←(OPRD)-1
例如:DEC VARB ;VARB是字节变量
操作数OPRD可以是通用寄存器,也可以是存储单元。在相减时,把操作数作为一个无符号数对待。这条指令执行的结果影响标志ZF、SF、OF、PF和AF,但不影响CF。 7.取补指令NEG 格式:NEG OPRD
执行的操作:(OPRD)← 0-(OPRD)
这条指令对操作数取补,就是用零减去操作数OPRD,再把结果送回OPRD。(各位取反末尾加1)操作数可以是通用寄存器,也可以是存储单元。 例如:NEG AL
NEG VARW[SI] ;有效地址就是VARW的位移加SI的值 如在字节操作时对-128取补,或在字操作时对-32768取补,则操作数不变,但OF被置1。其它均为0。此指令的执行结果影响CF、ZF、SF、OF、AF和PF,操作数为0时,求补运算的结果使CF=0,其它情况则均为1。
8.比较指令CMP
格式:CMP OPRD1,OPRD2
这条指令完成操作数OPRD1减去操作数OPRD2,运算结果不送到OPRD1。但影响标志CF、ZF、SF、OF、AF和PF。 例如:CMP SI,DI CMP CL,5 CMP DX,[BP-4]
比较指令主要用于比较两个数的关系,是否相等,谁大谁小。执行了比较指令后,可根据ZF是否置位,判断两者是否相等;如果两者是无符号数,则可根据CF判断大小;如果两者是有符号数,则要根据SF和OF判断大小。
遇到双精度数用AX存放低字,用DX存放高字。先进行低字的加减法,再进行高字的加减法,因为在高位还要算入带进位的加减法。
例如:写出对存放在DX和AX中的双字长数求补的指令序列 答案:NEG DX NEG AX SBB DX,0
如果是双字数进行求补,首先对高位(DX)进行求补,然后再对低位(AX)求补、求补:用0减或者各位取反末尾加一。
(三)乘除运算指令
乘除运算指令分为无符号数运算和有符号数运算指令,这点与加减法运算指令不同。乘除运算指令对标志位的影响有些特别 1.乘法指令
在乘法指令中,一个操作数总是隐含在寄存器AL(8位数相乘)或者AX(16位数相乘)中,另一个操作数可以采用除立即数方式以外的任一种寻址方式。 (1)无符号数乘法指令MUL 格式:MUL OPRD
在乘法指令里,目的操作数必须是累加器。两个8位数相乘得到的是16位乘积存放在AX中,两个16位数相乘得到的是32位乘积存放在DX、AX中,DX存放高位字,AX存放低位字。 如果乘积结果的高半部分(字节相乘时为AH,在字相乘时为DX)不等于零,则标志CF=1,OF=1,否则CF=0,OF=0。所以如果CF=1和OF=1表示在AH或DX中含有结果的有效数。 (2)有符号数乘法指令IMUL 格式:IMUL OPRD
这条指令把被乘数和乘数均作为有符号数,此外与指令MUL完全类似。如果乘积结果的高半部分