8086/8088汇编指令系统剖析(二)

 

标志操作指令

 

 

 

8086/8088指令集中,有一部分指令是专门对标志寄存器或标志位进行的。包括四条标志寄存器传送指令和七条专门用于设置或者清除某些标志位的指令。

 

 

 

 

 

1.标志传送指令

 

标志传送指令属于数据传送指令组。

 

1)指令LAHFLoad AH with Flags

 

指令LAHF采用固定寻址方式,其指令格式如下:

 

 

 

LAHF

 

 

 

该条指令把标志寄存器的低8位(包括标志SF,零标志ZF,辅助进位标志AF,奇偶标志PF和进位标志CF)传送到寄存器AH的指定位,即相应地传送至寄存器AH的位76420,其他的位(位531)的内容无定义。

 

 

 

这条指令本身不影响这些标志位和其他标志。

 

2)指令SAHF采用固定寻址方式,其格式如下:

 

 

 

SAHF

 

 

 

该条指令与指令LAHF刚好相反,把寄存器AH的指定位送至寄存器低8位的SFZFAFPFCF标志位。因而这些标志的内容就要受到影响,并取决与AH中相应位的状态。但是这条指令不影响溢出标志OF,方向标志DF,中断标志IF和追踪标志TF,也既不能影响寄存器标志的高位字节,例如:

 

 

 

MOV AH0C1H

 

SAHF CF = 1PF = 0AF = 0ZF = 1SF = 1

 

 

 

3)指令PUSHF

 

 

 

指令PUSHF的格式如下:

 

 

 

PUSHF

 

 

 

该指令把标志寄存器的内容压入堆栈,即先把堆栈指针寄存器SP的值减2,然后把标号寄存器的内容送入有SP所指的栈顶。

 

这条指令不影响标志。

 

 

 

4)指令POPF

 

 

 

指令POPF的格式如下:

 

 

 

POPF

 

 

 

该条指令把当前堆栈顶的一个字传送到标志寄存器,同时相应的修改堆栈指针,即把堆栈指针寄存器SP的值加2.

 

在执行该指令后,标志寄存器各位会发生相应的变化。

 

这条指令和PUSHF指令一起用可以保存和恢复标志寄存器的内容,即保存和恢复各标志的值。另外,这两条指令也可以用来改变追踪标志TF。在8086/8088指令系统中,没有专门设置清楚TF标志的指令,为了改变TF标志,可先用PUSHF指令将标志压入堆栈,然后在设法改变栈顶字单元中的第八位(那整个标志寄存器看成一个字),再用POPF指令把该字弹回到标志寄存器,这样其余的标志不受影响,而只有TF标志需要改变了。

 

 

 

2.标志位操作

 

 

 

标志位操作指令属于处理器控制指令组,它们仅对指令规定的标志产生指令规定的影响,对其它标志没有影响。

 

1)清进位标志指令CLCClear Carry flag

 

清进位标志指令的格式如下:

 

 

 

CLC

 

 

 

该指令使进位标志为0

 

 

 

2)置进位标志指令STCSet Carry flag

 

 

 

STC

 

 

 

该指令使进位标志为1

 

 

 

3)进位标志取反指令CMCCoMplement Carry flag

 

 

 

进位标志取反指令的格式如下:

 

 

 

CMC

 

 

 

该条指令使进位标志取反。如CF1,则使CF0;如果CF0,则CF1

 

 

 

4)清方向标志CLDClear Direction flag

 

 

 

清方向标志指令的格式如下:

 

STD

 

 

 

该指令使方向标志DF1.从而在执行串操作指令时,使地址按递减方式变化。

 

 

 

6)清中断指令CLIClear Interrupt enable flag

 

清中断指令的格式如下:

 

 

 

CLI

 

 

 

清中断允许标志IF0,于是CPU就不响应来自外部的可屏蔽中断。

 

但对不可屏蔽中断和内部中断都没影响。

 

 

 

7)置中断允许标志STISet Interrupt enable flag

 

置中断允许标志指令格式如下:

 

 

 

STI

 

 

 

该条指令是中断允许标志IF1,则CPU可以响应可屏蔽中断。

 

 

 

 

 

加减运算指令

 

 

 

8086/8088提供加,减,乘和除四种基本运算操作。这些操作都可以用于字节或字的运算,也可以用于无符号的运算或有符号数的运算。有符号数用补码表示。加减运算指令不再分为无符号数运算指令和有符号数运算指令,而乘除运算指令还分为无符号数运算和有符号数运算指令。另外,8086/8088还提供了各种十进制算数运算调整指令。

 

关于加减运算指令,有如下几点通用说明,请予以注意:

 

1)加减运算指令对无符号数和有符号数的处理一视同仁。即作为无符号数而影响CFAF,也有作为有符号数影响标志OFSF,当然总会影响标志ZF。加减运算指令也要影响标志PF。有些指令稍有例外。

 

2)总是只有通用寄存器或存储单元可用于存放运算结果。如果参与运算的操作数有两个,则最多只能有一个存储器操作数。

 

3)如果参与运算的操作数有两个,则他们的类型必须一致,即同时为字节,或同时为字。

 

4) 存储取操作数可采用标准四种存储器操作数寻址方式。

 

 

 

1.加法指令

 

 

 

1)普通加法指令ADD

 

普通加法指令的格式如下:

 

 

 

ADD OPRD1OPRD2

 

 

 

这两条指令完成两个操作数相加,结果送至目的操作数OPRD1,即:

 

 

 

OPRD1 <= OPRD1 + OPRD2

 

 

 

例如:

 

 

 

ADD AL5

 

ADD ALAH

 

ADD DIDI

 

ADD BLVARB VARB是字节变量

 

ADD VARWSI VARW是字变量

 

ADD [BX+SI-3]AX

 

 

 

我们用下面的程序片段说明加法指令及其对标志的影响,同时说明8位数据寄存器与16位数据寄存器间的关系。

 

 

 

MOV AX7896H AX=7896H,即AH=78AL=96

 

;各标志位保持不变

 

MOV ALAH AL=0EHAH=78,即AX=780EH

 

CF=1ZF=0SF=0OF=0AF=0PF=0

 

ADD AHAL AH=86HAL=0EH,即AX=860EH

 

CF=0ZF=0SF=1OF=1AF=1PF=0

 

ADD AL0F2H AL=00HAH=86H,即AX=8600H

 

CF=1ZF=1SF=0OF=0AF=1PF=1

 

ADD AX1234H CF=0ZF=0SF=1OF=0AF=0PF=0

 

 

 

2)带进位加指令ADCAdd with Carry

 

 

 

带进位加指令的格式格式如下:

 

 

 

ADC OPRD1OPRD2

 

 

 

这条指令与ADD指令类似,完成两个操作数相加,但是要把进位CF的现行值加上去,把结果送至目的操作数OPRD1,即:

 

 

 

OPRD1 <= OPRD1 + OPRD2 +CF

 

 

 

例如:

 

 

 

ADC AL[SI]

 

ADC DXAX

 

ADC DXVARW VARW是字变量

 

 

 

ADC指令主要用于多字节运算中。尽管在8086/8088中可以进行16位运算,但是16位二进制数能表达的整数的范围还是很有限的,为了扩大数的范围,仍然需要多字节运算。例如,有两个四字节的数相加,加法要分两次进行,先进行低两字节相加,然后再做高两字节相加。在高两字节相加时,要把低两字节相加以后可能出现的进位考虑进去,用ADC指令实现这点很方便。

 

下面的程序片段实现两个四字接数相加,注意传送指令不影响标志:

 

 

 

MOV AXFIRST1 FIRST1是存放第一个数低两字节的变量

 

ADD AXSECOND1 SECOND1是存放第二个数低两字节的变量

 

MOV THIRD1AX ;保存低两字节相加的结果到THIRD1变量中

 

MOV AXFIRST2 FIRST2是存放第一个数高两字节的变量

 

ADC AXSECOND2 SECOND2是存放第二个数高两字节的变量

 

MOV THIRD2AX ;保存结果的高两字节到THIRD2变量中

 

 

 

3)加1指令INCINCrement

 

1指令的格式如下:

 

 

 

INC OPRD

 

这条指令完成对操作数OPRD1,然后把结果送回OPRD,即:

 

 

 

OPRD <= OPRD + 1

 

 

 

例如:

 

 

 

INC AL

 

INC VARB VARB是字节变量

 

 

 

操作数DST可以是通用寄存器,也可以是存储单元。这条指令执行的结果影响标志ZFSFOFPFAF,但它不影响CF

 

 

 

该指令主要用于调整地址指针和计数器。

 

 

 

 

 

2.减法指令

 

 

 

1)普通减法指令SUB

 

 

 

普通减法指令的格式如下:

 

 

 

SUB OPRD1OPRD2

 

 

 

这条指令完成两个操作数相减,从OPRD1中减去OPRD2,结果送到目标操作数OPRD1中,即:

 

 

 

OPRD1 <= OPRD1 – OPRD2

 

 

 

例如:

 

 

 

SUB AH12

 

SUB BXBP

 

SUB AL[BX]

 

SUB BXVARW VARW是字变量

 

SUB [BP-2]AX

 

 

 

我们用下面的程序片段说明减法指令及其对标志的影响,同时再次说明8位数据寄存器与16位数据寄存器的关系。

 

 

 

MOV BX9048H BX=9048H,即BH=90HBL=48H

 

SUB BHBL BH=48HBL=48H,即BX=4848H

 

CF=0ZF=0SF=0OF=1AF=1PF=1

 

SUB BLBH BL=00HBH=48H,即BX=4800H

 

CF=0ZF=1SF=0OF=0AF=0PF=1

 

SUB BL5 BL=FBHBH=48H,即BX=48FBH

 

CF=1ZF=0SF=1OF=0AF=1PF=0

 

SUB BX8F34H BX=B9C7H,即BH=B9HBL=C7H

 

CF=1ZF=0SF=1OF=1AF=0PF=0

 

 

 

2)带进(借)位减指令SBBSubtract with Borrow

 

带借位指令的格式如下:

 

 

 

SBB OPRD1OPRD2

 

 

 

这条指令与SUB指令类似,在操作数OPRD1减去OPRD2的同时还要减借位(进位)标志CF的现行值,即:

 

 

 

OPRD1 <= OPRD1 - OPRD2 – CF

 

 

 

例如:

 

 

 

SBBALDL

 

SBBDXAX

 

 

 

该指令主要用于多字节数相减的场合

 

 

 

3)减1指令DEC

 

 

 

1指令的格式如下:

 

 

 

DEC OPRD

 

 

 

这条指令把操作数OPRD1,并把结果送回OPRD,即:

 

 

 

OPRD <= OPRD – 1

 

 

 

例如:

 

 

 

DEC BX

 

DEC VARB VARB是字节变量

 

 

 

操作数OPRD可以是通用寄存器,也可以是存储单元。在相减时,把操作数作为一个无符号对待。这条指令执行的结果影响标志ZFSFOFPFAF,但它不影响CF

 

该指令主要用于调整地址指针和计数器。

 

 

 

4)取补指令NEG

 

取补指令的格式如下:

 

 

 

NEG OPRD

 

 

 

这条指令对操作数取补,就是用零减去操作数OPRD,再把结果送回OPRD,也即:

 

OPRD <= 0 – OPRD

 

 

 

例如:

 

NEG AL

 

NEG VARW[SI]

 

 

 

 

 

5)比较指令CMP

 

比较指令CMP的格式如下:

 

 

 

CMP OPRD1OPRD2

 

 

 

这条指令完成操作数OPRD1减去操作数OPRD2,运算结果不送到OPRD1,但影响CFZFSFOFAFPF。例如:

 

 

 

CMP SIDI

 

CMP CL5

 

CMP DX[BP-4]

 

 

 

比较指令主要用于比较两个数的关系,是否相等,谁大谁小。在执行比较指令后,可根据ZF是否置位,判断两者是否相等;如果两者是无符号数,则可根据CF判断CF大小;如果两者是有符号数,则要根据SFOF判断大小。

 

例,设有两个64位数按“高高低低”原则存放在同一个段的两个缓冲区DATA1DATA2中,现在需要计算DATA1-DATA2。下面程序片段计算DATA1-DATA2,结果存放在DATA1中,可能发生的借位保留在CF中:

 

.....

 

MOV CX4

 

SUB BXBX

 

NEXTMOV AXDATA2[BX]

 

SBB DATA1[BX]AX

 

INC BX

 

INC BX

 

DEC CX

 

JNZ NEXT

 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值