汇编语言 -第十一章

第十一章 标志寄存器

一、各标志位说明
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]&mdash;&mdash;>目的:byte ptr es:[di]
依据df值,使得si/di递增/减1。
(2)movsw
源:word ptr ds:[si]&mdash;&mdash;>目的: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


 

检测点11.3

(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


posted @ 2013-08-30 14:10  tsembrace  阅读(844)  评论(0编辑  收藏  举报