第十一章 标志寄存器
8086CPU的标志寄存器有16位,其中存储的信息通常被称为程序状态字(PSW:program status word)
本章中的标志寄存器(以下简称为flag)是我们要学习的最有一个寄存器
flag寄存器是按位起作用的,也就是说,它的每一位都有专门的含义,记录特定的信息
8086CPU的flag寄存器的结构:
1.flag的1、3、4、12、13、14、15位共7位在8086CPU中没有使用,不具有任何含义
而0、2、4、6、7、8、9、10、11位共9位都具有特殊的含义
2.示意图
11.1 ZF标志
1.flag的第6位是ZF,零标志位。zero flag
它记录相关指令执行后,
1.结果为0,ZF=1
2.结果不为0,ZF=0
2.示例:
mov ax,1
sub ax,1
指令执行后,结果为0,则ZF=1
mov ax,2
sub ax,1
指令执行后,结果不为0,则ZF=0
3.注意,在8086CPU的指令集中,有的指令的执行会影响标志寄存器
比如:add、sub、mul、div、inc、or、and等
他们大都是运算指令(逻辑运算或者算术运算)
有的指令的执行对标志寄存器没有影响,
比如:mov、push、pop等,他们大都是传送指令
11.2 PF标志
flag的第2位是PF,奇偶标志位 parity(平等的意思) flag
它记录指令执行后,结果的所有二进制位中1的个数
1.为偶数,PF=1
2.为奇数,PF=0
11.3 SF标志
1.flag的第7位是SF,符号标志位 sign flag
2.它记录指令执行后
1.结果为负。sf=1
2.结果为正,sf=0
sf标志,就是CPU对有符号数运算结果的一种记录,它记录数据的正负
sf标志把所有数当作有符号数
如果把数据当作无符号数运算,sf的值则没有意义,虽然相关指令会影响它的值
3.也就是说,CPU在执行add等指令时,是必然要影响sf标志位的值
至于我们需不需要这种影响,那就看我们如何看待指令所进行的运算
11.4 CF标志
1.flag的第0位是CF,进位标志位
一般请况下,在进行无符号数运算的时候,
它记录了运算结果的最高有效位向更高位的进位值,
或从更高位的借位值
代表假想的更高位
2.CPU在运算时,不会丢弃进位值,而是记录在一个特殊的寄存器的某一位上
8086CPU就用flag的cf为来记录这个进位值(加法时),借位也一样(减法时)
3.在debug中的显示 NC:no carry(没有进位),CY:carry yes(有进/借位)
4.无符号的时候产生的结果
11.5 OF标志
flag中的第11位(OV:overflow有溢出),NV(没溢出)
进行有符号数运算的时候,如果结果超过了机器所能表示的范围称为溢出
1.这里所讲的溢出,只是对有符号数运算而言
就像进位只是相对于无符号数而言!
2.一定要注意cf和of的区别
当需要把机器码看成有符号数则使用of
当需要把机器码看成无符号数则使用cf
对于无符号数,98+99没有进位 ,cf=0
对于有符号数,98+99发生溢出 ,of=1
11.6 adc标志
adc是带进位的加法指令,他利用了cf上记录的进位值
1.格式:adc 操作对象1,操作对象2
2.功能:操作对象1=操作对象1+操作对象2+cf
比如:adc ax,bx实现的功能是:
(ax)=(ax)+(bx)+cf
3.执行adc指令的时候,加上的cf的值的含义,由adc指令前的指令决定
也就是说,关键在于所加上的cf值是被什么指令设置的
4.如果cf是被sub指令设置的,那么他的含义就是借位值
如果是被add指令设置的,那么它的含义就是进位值
5.下面的指令和add ax,bx具有相同的结果
add al,bl
adc ah,bh
CPU提供adc指令的目的,就是来进行加法的第二步运算的
adc指令和add指令相配合就可以对更大的数据进行加法运算
【实验:编程计算1EF000H+201000H,结果放在ax(高16位)和bx(低16位)中】
mov ax,001eh
mov bx,0f000h
add bx,1000h ;低位和低位相加存入bx ,cf保留进位
adc ax,0020h ;高位和高位相加存入ax ,最后+cf
11.7 sbb标志
sbb是带借位减法指令,他利用了cf位上记录的借位值
1.格式:sbb 操作对象1,操作对象2
2.功能:操作对象1=操作对象1-操作对象2-cf
3.利用sbb指令,我们可以对任意大的数据进行减法运算
4.sbb和adc是基于相同的思想设计的两条指令,
在应用思路上和adc类似
11.8 cmp标志
1.cmp是比较指令,功能相当于减法指令,只是不保存结果
2.cmp指令执行后,将对标志寄存器产生影响
3.其他相关指令通过识别这些被影响的标志寄存器,来得知比较结果
4.cmp指令格式:cmp 操作对象1,操作对象2
5.功能:计算操作对象1-操作对象2,但并不保存结果,仅仅根据计算结果对标志寄存器进行设置
6.比如:cmp ax,ax
做(ax)-(ax)的运算,结果为0,但并不在ax中保存,仅影响flag的相关位
指令执行后
zf=1 ;结果为0
pf=1 ;结果的1的个数为偶数
sf=0 ;结果为正号
cf=0 ;结果没有产生进位或借位
of=0 ;结果没有溢出
7.根据flag,判断cmp指令的结果(无符号数)
8.cmp既可以对无符号数进行比较,也可以对有符号数进行比较
cmp 操作数1,操作数2 ;操作数1、操作数2都是有符号数
1.of=0,说明没有溢出,逻辑上真正结果的正负=实际结果的正负
of=0,sf=1 则 操作数1比操作数2小
of=0,sf=0 则 操作数1比操作数2大
2.of=1,说明有溢出,逻辑上真正结果的正负与实际结果的正负相反
of=1,sf=1 则 操作数1比操作数2大
of=1,sf=0 则 操作数1比操作数2小
11.9 检测比较结果的条件转移指令
1.这些条件转移指令通常和cmp相配合使用
2.因为cmp指令可以同时进行两种比较,无符号数和有符号数的比较
所以,这些转移指令也分为两种,即:
1.根据【无符号数】的比较结果进行转移的条件转移指令,
他们检测zf、cf的值
2.根据【有符号数】的比较结果进行转移的条件转移指令
他们检测sf、of和zf的值
3.无符号比较,条件转移指令小结【无符号,6个】
1.je 等于则转移 zf=1
2.jne 不等于则转移 zf=0
3.jb 低于则转移 cf=1 【b表示below】
4.jnb 不低于则转移 cf=0
5.ja 高于则转移 cf=0,zf=0【a表示above】
6.jna 不高于则转移 cf=1或zf=1
11.10 DF标志和串传送指令
1.flag的第10位DF,方向标志位
在串处理指令(movsb,movsw)中,控制每次操作后si、di的增减
df=0:每次操作后si,di递增
df=1:每次操作后si,di递减
2.格式:movsb
3.功能:(以字节为单位传送)
1.((es)*16+(di))=((ds)*16+(si))
2.如果df=0,则:(si)=(si)+1
(di)=(di)+1
如果df=1,则:(si)=(si)-1
(di)=(di)-1
3.功能文字描述
movsb的功能是将ds:si指向的内存单元中的字节
送入es:di中,然后根据标志寄存器df位的值,
将si和di递增或递减
4.movsw 传送一个字
5.movsb和movsw都和rep配合使用
格式:rep movsb
rep的作用根据cx的值,重复执行后面的串传送指令
6.cld指令和std指令
cld指令:将标志寄存器的df置为0【c:clear】
std指令:将标志寄存器的df置为1【s:set】
11.11 pushf和popf
pushf:将标志寄存器的值压栈
popf:从栈中弹出数据,送入标志寄存器中
pushf和popf为直接访问标志寄存器提供了一种方法
11.12 标志寄存器在debug中的表示