第十一章 标志寄存器FLAG
标志寄存器的作用:存储相关指令的某些执行结果;为CPU执行相关指令提供行为依据;控制CPU相关工作方式。
标志寄存器有16位,其中存储的信息被称为程序状态字(PSW).
空的内存单元没有意义。
ZF标志
第6位,零标志位,记录相关指令执行后结果是否为0. 如果结果为0,ZF=1,否则ZF=0.
注:能够影响标志位的一般是运算指令,比如add, sub, mul, div, inc, or, and
而大多数传送指令是不影响标志位的,比如mov, push, pop
PF标志
第2位,奇偶标志位,记录相关指令执行后,其结果(binary)的所有bit位中1的个数是否为偶数。如果1的个数为偶数(包括0),PF=1,若为奇数,PF=0.
SF标志
第7位,符号标志位,记录相关指令执行后,其结果(看做有符号数)是否为负。如果为负,SF=1,否则SF=0.
计算机中通常用补码表示有符号数,一个数据可以被看成是有符号数,也可以被看做是无符号数。比如10000001B,无符号数表示129,有符号数表示-127. 在用CPU执行运算指令的时候,会得到代表两种结果的同一信息。关键在于我们的程序需要哪一种结果。
如果将数据当做有符号数,SF指示结果的正负,如果当做无符号数则SF没有意义。
一些指令有可能会同时影响到多个标志位。
检测点11.1
1,1,0
1,1,0
1,1,0
1,1,0
0,0,0
0,1,0
0,1,0 (结果最高位不为1,SF=0)
CF标志
第0位,进位标志位,在进行无符号数运算时,记录运算结果的最高有效位向更高位的进位值,或从更高位的借位值。
eg 加法进位
mov al,98h
add al,al ;执行后,(al)=30h, CF=1, 记录最高有效位向更高位进位的信息
add al,al ;执行后,(al)=60h, CF=0
eg 减法借位
mov al,97h
sub al,98h
; 相当于计算197H-98H, 执行后,(al)=FFh, CF=1,记录了向更高位的借位
sub al,al ; 执行后,(al)=0, CF=0
OF标志
第11位,溢出标志位。OF是对有符号数运算有意义的标志位。
溢出:在进行有符号数运算时,结果超过了机器所能表示的范围(-128~127 for 8 bit , -65536~65535 for 16 bit)。
进行有符号数运算时,可能由于发生溢出导致结果错误,因此需要CPU记录溢出。
对于无符号数运算,CPU用CF位记录进位;对于有符号数运算,CPU用OF位记录溢出。
检测点11.2
0,0,0,1,1
0,0,0,1,1
0,0,1,0,1
0,0,1,0,1
1,1,0,1,1
1,1,0,1,1
1,0,0,0,0
1,0,0,0,0
0,1,1,0,1
adc指令
带进位加法指令,利用CF位上记录的进位值。
adc 对象1,对象2 功能:对象1=对象1+对象2+CF
加上CF位的意义是什么?关键在于CF的值是被什么指令设置的。如果是sub,那含义是借位,如果是add,则为进位。
add ax,bx与下面的指令等价:
add al,bl(低位直接相加)
adc ah,bh(高位相加再加上低位相加产生的进位值)
我们可以利用add和adc指令对更大的数据进行加法运算。
在写程序时,有时候需要考虑使用add对CF位的影响,如想避免该影响,应该改用inc, loop这些不影响CF位的指令。
sbb指令
带借位减法指令,利用CF上记录的借位值。
sbb 对象1,对象2 功能:对象1=对象1-对象2-CF
利用sbb指令可以对任意大的数据进行减法运算。其设计思路与应用和adc指令类似。
比较指令。其功能相当于sub指令,只是不保存结果,仅仅根据计算结果改变标志寄存器的值,其它指令将通过识别标志寄存器的改变来判断cmp指令的执行结果。
cmp 对象1,对象2
cmp ax,bx 执行后:
ZF=1,则(ax)=(bx)
ZF=0,则(ax)≠(bx)
CF=1,则(ax)<(bx) //(ax)-(bx)产生借位
CF=0,则(ax)≥(bx)
CF=0且ZF=0,则(ax)>(bx)
CF=1或ZF=1,则(ax)≤(bx)
以上为cmp进行无符号数比较。
下面为有符号数比较:
cmp ah,bh 执行后:
ZF=1,则(ah)=(bh)
ZF=0,则(ah)≠(bh)
SF=1,OF=0,则(ah)<(bh)
SF=1,OF=1,则(ah)>(bh) //如果因为溢出导致结果为负,那么逻辑上的真正结果必定为正。
SF=0,OF=1,则(ah)<(bh) //如果因为溢出导致结果为正,那么逻辑上的真正结果必定为负。
SF=0,OF=0,则(ah)≥(bh)
条件转移指令:根据一定条件下的判断结果,确定是否执行IP的修改。如jcxz 检测cx是否为0,为0时才修改IP。
所有条件转移指令的转移位移都是-128~127.
大多数条件转移指令都是通过检验标志寄存器的相关标志位(受cmp指令影响的标志位)来决定是否修改IP。因此条件转移指令通常和cmp搭配使用,表现出高级语言中IF语句的功能。
条件转移指令根据cmp的特性也分为两种:
(1)根据无符号数比较结果进行转移(检测ZF,CF):
je = jump equal
jne = jump not equal
jb = jump below
ja = jump above
当然条件转移指令也可以不与cmp搭配使用,比如只要标志位ZF=1,je指令就会执行转移。
检测点11.3
(1)
jb s0 (<32)
ja s0 (>128)
(2)
jna s0 (≤32)
jnb s0 (≥128)
DF标志
第10位,方向标志位。在串处理指令中,控制每次操作后si,di的增减。
df=0,每次操作后si,di递增
df=1,每次操作后si,di递减
串传送指令:
movsb 相当于
即将ds:si指向内存单元中的字节送到es:di中,然后根据df位的值对si,di进行操作。
类似还有movsw指令,即将ds:si指向内存单元中的字送到es:di中,然后根据df位的值对si,di进行操作(增减2)。
一般来说,movsb和movsw都和rep指令一起使用:rep movsb
相当于:
s: movsb
loop s
rep的作用是根据cx的值,重复执行后面的串传送指令,可以实现(cx)个字符的传递。
8086提供指令对df标志位进行设置,从而使程序员可以控制传送方向。
cld指令将df置0
std指令将df置1
pushf: 将标志寄存器的值压栈。
popf: 从栈中弹出数据,送入标志寄存器。
检测点11.4
(ax)=45H
(pushf执行后PSW置0,pop ax执行后 ax=0000 0000 0100 0101B)
(转)调试程序DEBUG如何表达标志状态?
溢出OV(overflow,OF=1)
无溢出NV(no overflow,OF=0)
减量DN(direction down,DF=1)
增量UP(direction up,DF=0)
允许中断EI(enable interrupt,IF=1)
进制中断DI(disable interrupt,IF=0)
负NG(negative,SF=1)
正PL(plus,SF=0)
零ZR(zero,ZF=1)
非零NZ(no zero,ZF=0)
辅助进位AC(auxiliary carry,AF=1)
无辅助进位NA(no auxiliary carry,AF=0)
偶校验PE(even parity,PF=1)
奇校验PO(odd parity,PF=0)
进位CY(carry,CF=1)
无进位NC(no carry,CF=0)
实验11
assume cs:codesg, ss:stacksg
datasg segment
db "Beginner's All-purpose Symbolic Instruction Code.",0
datasg ends
stacksg segment
dw 8 dup (0)
stacksg ends
codesg segment
begin:
mov ax,datasg
mov ds,ax
mov si,0
call letterc
mov ax,4c00h
int 21h
letterc:
push cx ;注意代码中对cx的利用
push si
pushf
mov ch,0
start:
mov cl,ds:[si]
jcxz zero
cmp cl,97
jb next
cmp cl,122
ja next
sub cl,20h
mov ds:[si],cl
next:
inc si
jmp start
zero:
popf
pop si
pop cx
ret
codesg ends
end begin