汇编语言 -第十一章
第十一章 标志寄存器
一、各标志位说明
1、ZF标志
*名称:零标志位
*位置:第6位
*作用:记录相关指令执行后,结果是否为0.如果结果为0,则zf位为1;反之为0.
2、PF标志
*名称:奇偶标志位
*位置:第2位
*作用:记录相关指令执行后,结果所有bit位中为1的个数是否为偶数.如果为偶数,则pf位为1;反之为0.
3、SF标志
*名称:符号标志位
*位置:第7位
*作用:记录相关指令执行后,结果是否为负.若为负,则sf位为1;反之为0。
4、CF标志
*名称:进位标志位
*位置:第0位
*作用:记录相关指令执行后,结果是否向更高位借位(进位)。若有借位(进位),则cf位为1;反之为0.
*备注:只相关于无符号数的运算。
5、OF标志
*名称:溢出标志位
*位置:第11位
*作用:记录相关指令执行后,结果是否溢出.
*备注:(1)溢出是指是否超过了机器可以表示的范围,对8位来说,有符号数的表示范围为-128~127.
(2)溢出标志位只相关于有符号数的运算
如何理解CF只针对无符号数,OF只针对有符号数?
首先,以8位数据为例,进位或借位是表示在这8位数据再高一位的位置上借数,也就是说此时这8位全都作为数字数据的,最高位并不作为符号位。
比如mov al,98 add al,99之后
(al)=197,即0c5h,没有产生进位,所以cf=0;若al表示有符号数,则明显197超出了8位能表示的有符号数范围(-128~127),所以of=1.
在比如mov al,128 add al,129
(al)应该等于257,可实际上al寄存器放不下这个数据,需要9位来表示257:1 0000 0001;此时产生了进位,则cf=1;
若将al看为有符号数,则开始al=-128,加上129表示的有符号数为-127.相加后(al)=1,没有超出表示范围,则of=0.
通过上述,概况:对于无符号数,若cf=1则最终结果不准确;对于有符号数,若of=1,则最终结果不准确。
6、DF标志
*名称:方向标志位
*位置:第10位
*作用:如果df=0,每次操作后si/di递增;
如果df=1,每次操作后si/di递减。
二、相关指令
*adc\sbb:只应用于无符号数的计算。
*cmp
格式:cmp a1,a2
操作:判断(a1-a2)的值,以影响相关标志位,但该值不保存。
说明:cmp相关的运算需要依据实际情况来看是针对无符号数还是有符号数。
引申:
(1)对无符号数运算来说,cmp a,b,很容易得出:
if zf=1 ,a=b
if zf=0&cf=0,a>b
if zf=0&cf=1,a<b
(2)对有符号数运算来说,cmp a,b,则
if zf=1,a=b
if zf=0&of=0:zf=0说明a!=b,of=0说明未发生溢出,对于有符号数的运算(a-b),结果未溢出,按以下几种情况分析:
A、a>=0&b>=0,这种情况下,对有符号数来说,a-b永远不会溢出
B、a>=0&b<=0,这种情况下,只有当(a+|b|)<=127的情况下才不会溢出
C、a<0&b>0,这种情况下,只有当(b+|a|)<=128的情况下才不会溢出
D、a<0&b<0,这种情况下,a-b永远不会溢出
if zf=0&of=1:zf=0说明a!=b,of=1说明发生溢出,对于有符号数的运算(a-b),结果溢出,情况分析同上步(相反);
可见,对有符号数而言,仅仅通过zf和of的值,无法判断两数的大小关系。
若要判断a,b大小,须再看sf的值,书上p225有结论:
T1、如果溢出且实际结果为负,那么逻辑上真正结果为正;
T2、如果溢出且实际结果为正,那么逻辑上真正结果为负;
下面来具体分析一下:
T1:of=1&sf=1,求证a>b
证明:
1、of=1可得出 -128>(a-b)>=-255 or 255>=(a-b)>127
2、sf=1可得出(a-b)的补码在第7位(最高位)为1.
3、分析[-255,-128)和(127,255]的补码表示形式,找出第7位为1的范围。
(-129)补=1111 1111 0111 1111
(-130)补=1111 1111 0111 1110
(-131)补=1111 1111 0111 1101
...
(-255)补=1111 1111 0000 0001
可看出[-255,128)区段的第7位为0,不符合。因此可以推断(a-b)只可能属于区间(127,255],接下来再具体分析证实一下:
(128)补=(128)原=0000 0000 1000 0000
(129)补=(129)原=0000 0000 1000 0001
...
(255)补=(255)原=0000 0000 1111 1111
可看出[-255,128)区段的第7位为1,符合。
因此255>=(a-b)>127,而对于8bit位的a-b来说,只有在a>0&b<0的情况下才可能发生;因此a>b.
故而得证。
T2:of=1&sf=0,求证a<b
同理可证。
总结:
这是这章乃至整本书里最让我困惑的问题之一,我无法从王爽书上那简单的话语可以得出相应的结论。
在上述证明t1-t2的时候我考虑了一个前提,即:计算机并不知道我们要进行的是否为无符号数的计算,但计算机提供了补码这个机制,来应对我们逻辑上所能想的所有情况,来使得结果正确。
比如对(-1)-128这个运算来说,逻辑上的结果为-129。
1、如果我们考虑的是8bit位的运算,则产生了溢出,of=1,最终8bit位结果为0111 1111;而0111 1111表示的是127,逻辑上127这个结果明显是错误的;可对于计算机运算结果里这8位保存的二进制真的是没有意义的么?当然不是。
2、如果我们考虑的是16bit位的运算,则不产生溢出,of=0,最终16bit位结果为1111 1111 0111 1111,可以看出其低8位的结果和上述相一致。
也就是说,对于情况1来说,因为溢出了,真实的值并不能只通过这8位来表示,但这8位保存的又是真实值的一部分组成。
对于上面的证明过程也是应用了这一点,对于8bit位的有符号数运算,其8位溢出则必然可以用16位补码表示,而这8位又是16位补码的低8位。
*je\jne\jb\jnb\ja\jna
*串传送指令
(1)movsb
源:byte ptr ds:[si]——>目的:byte ptr es:[di]
依据df值,使得si/di递增/减1。
(2)movsw
源:word ptr ds:[si]——>目的:word ptr es:[di]
依据df值,使得si/di递增/减2。
(3) rep
一般和串传送指令搭配使用,比如:
rep movsb,相当于:
s: movsb
loop s
(4) cld:将df位置0;std:将df位置1.
(5)pushf:将标志寄存器压栈;popf:取栈内数据存入标志寄存器中
检测点11.1
写出下面每条指令执行后,ZF,PF,SF标志位的值
sub al,al ZF=1,PF=1,SF=0 mov al,1 ZF=0,PF=0,SF=0 push ax ZF=0,PF=0,SF=0 pop bx ZF=0,PF=0,SF=0 add al,bl ZF=0,PF=0,SF=0
检测点11.2
写出下面每条指令执行后,ZF,PF,SF,CF,OF标志位的值
sub al,al CF=0;OF=0;SF=0;ZF=1;PF=1 mov al,10H CF=0;OF=0;SF=0;ZF=1;PF=1 ;mov不影响标志位 add al,90h CF=0;OF=0;SF=1;ZF=0;PF=1 mov al,80h CF=0;OF=0;SF=1;ZF=0;PF=1 add al,80h CF=1;OF=1;SF=0;ZF=1;PF=1 mov al,0fch CF=1;OF=1;SF=0;ZF=1;PF=1 add al,05h CF=1;OF=0;SF=0;ZF=0;PF=0 mov al,7dh CF=1;OF=0;SF=0;ZF=0;PF=0 add al,0bh CF=0;OF=1;SF=1;ZF=0;PF=1
(1)补全程序,统计f000:0处32个字节中,大小在[32,128]数据的个数
mov ax,0f000h mov ds,ax mov bx,0 mov dx,0 mov cx,32 s:mov al,[bx] cmp al,32 jb s0 cmp al,128 ja s0 inc dx s0:inc bx loop s