汇编语言(王爽第三版)检测点11

11.1检测点答案

sub al,al     al=0h        ZF=1        PF=1        SF=0 

mov al,1      al=1h        ZF=1        PF=1        SF=0 

push ax       ax=1h        ZF=1        PF=1        SF=0 

pop bx        bx=1h        ZF=1        PF=1        SF=0 

add al,bl     al=2h        ZF=0        PF=0        SF=0 

add al,10     al=12h       ZF=0        PF=1        SF=0 

mul al        ax=144h      ZF=0        PF=1        SF=0

讲解:

       1首先我们认识到flag标志寄存器是记录指令结果的状态的。这里包括了2层含义:指令的结果(它是个值,二进制的,有的指令不影响值的变化,有的指令影响到了某个寄存器值的变化了,我们得看它的影响后的结果是什么?);根据这个结果对于flag标志寄存器的特定标志位产生了不同的值的变化。

       2. 此检测点涉及到的知识点是:

       ZF是flag的第6位,零标志位,记录指令执行后结果是否为0,结果为0时,ZF=1,它的作用:就是判断指令的结果是否为0,与是否是有符号和无符号数无关。

       PF是flag的第2位,奇偶标志位,记录指令执行后结果二进制中1的个数是否为偶数,结果为偶数时,PF=1;

作用:在代码传输的过程中,用于奇偶校验来确定代码(或二进制的值)在传输过程中是否正确被传输,有奇校验和偶校验二种。

       SF是flag的第7位,符号标志位,记录有符号运算结果是否为负数,结果为负数时,SF=1

在计算机中,使用1代表逻辑真,0代表逻辑假。

       作用:对于有符号数来说,判断正负(最高位是1,sf=1;最高位是0,sf=0),对于无符号数来说,此标志位无意义。

       3.这些标志位的变化是否是自动变化的?还是手动由程序来控制的呢?

       有的是自动的,有的是手动的。

       4. add、sub、mul、div 、inc、or、and等运算指令影响标志寄存器

mov、push、pop等传送指令对标志寄存器没影响。

       5.怎样看这些标志位呢?

在调试程序DEBUG中各标志位的显示方式(TF在DEBUG中不提供符号)

在debug中用这个指令r,在13个寄存器的最后,有类似这样的信息: NV   UP   EI   PL   NZ   NA   PO   NC ,它们就代表了flag状态寄存器的值,这些值根据英文大写的不同,代表不同的意义。

       在debug中,每种标志位的状态值都存在二种值:0和1,它们使用大写英文来描述。例如:如遇到ZR值代表指令结果为0,NZ代表指令结果不为0;注意:它们的值在debug中,某状态下只显示一种值,要么是ZR要么是NZ;不能同时出现的。结合debug讲解下:
这些符号代表的就是标志寄存器里常用标志位的值。这个是符号值对应表:

溢出标志OF(Over flow flag)          OV(1)                         NV(0)
方向标志DF(Direction flag)           DN(1)                          UP(0)
中断标志IF(Interrupt flag)            EI(1)                           DI(0)
符号标志SF(Sign flag)               NG(1)                          PL(0)
零标志ZF(Zero flag)                ZR(1)                         NZ(0)
辅助标志AF(Auxiliary carry flag)      AC(1)                          NA(0)
奇偶标志PF(Parity flag)              PE(1)                          PO(0)
进位标志CF(Carry flag)             CY(1)                         NC(0)

--它们的状态值

OF(Overflow Flag溢出标志)     OV(Overflow发生溢出)    NV(Non-Overflow未溢出)

SF(Signal Flag符号标志)          NG(Negetive负号)           PL(Plus加号,正号)

ZF(Zero Flag等于0标志)           ZR(Zero为零)                  NZ(Non-Zero非零)

PF(Parity Flag奇偶标志)            PE(Parity Even偶数)        PO(Parity Odd奇数)

CF(Carry Flag进位标志)            CY(Carry有进位)            NC(Non-Carry无进位)

       实例讲解下:使用debug程序看看,r指令。

AX=0000  BX=0000  CX=0000  DX=0000  SP=FFEE  BP=0000  SI=0000  DI=0000

DS=0B04  ES=0B04  SS=0B04  CS=0B04  IP=0102   NV UP EI PL ZR NA PE NC

红色标注的就是这些状态位的值,它所代表的含义看上面。

也可以使用rf指令查询状态寄存器的有效位的值。

-rf

NV UP EI PL ZR NA PE NC

答案讲解:

sub al,al     指令结果:(al)-(al)=0  (寄存器al的值为0)

al=0h        ZF=1        PF=1        SF=0     

使用debug查看:

-rf

NV UP EI PL ZR NA PE NC

ZR(Zero为零)   ZF=1  含义:指令结果为0;(另一种状态值:NZ    代表ZF=0  含义:指令结果不为0 )       

PE(Parity Even偶数) PF= 1  含义:指令结果中1的个数为偶数(因为al值为00000000,也就是说有0个1,0是偶数);(另一种状态值:PO  代表ZF=1  含义:指令结果中1的个数为计数)。这个有什么含义呢?

PL(Plus加号,正号) SF=0  含义:指令结果为非负数(在计算机中,存储0是按照计算机补码方式存储的,0代表的补码含义是什么?);(另一种状态值:NG  代表SF=1  含义:指令结果为负数)

以下同理:

特别提出:对于sf的判断,这里就有无符号数和有符号数的理解了,快捷判断方式是判断它的最高位是否为1(负数)、0(正数)。在此例中,由于最高位都是0,故sf=0,

 

11.2答案

写出下面每条指令执行后,ZF、PF、SF、CF、OF等标志位的值。

                    al          CF    OF    SF    ZF    PF

sub al,al     0h/0000 0000b      0     0     0     1     1

mov al,10h    10h/0010 0000b     0     0     0     1     1

add al,90h    a0h/1010 0000b     0     0     1     0     1

mov al,80h    80h/1000 0000b     0     0     1     0     1

add al,80h    0h/0000 0000b      1     1     0     1     1

mov al,0fch   0fch/1111 1100b    1     1     0     1     1

add al,05h    1h/0000 0001b      1     0     0     0     0

mov al,7dh    7dh/1111 1101b     1     0     0     0     0

add al,0bh    88h/1000 1000b     0     1     1     0     1

分析:

总结下以前学习到的标志位的含义:

CF—无符号数进位或借位标志

OF—溢出标志

SF—符号标志(0-正数;1-负数,是按照计算机补码方式的)

ZF—零标志(1-数值为0, 0-数值为非0值)

PF—奇偶标志(1-二进制数据1个个数为偶数;0-二进制数据1个个数为奇数)

技巧:

对于CF的值判断:直接对十六进制的操作数进行运算,得出结果,如果有进位或借位,CF=1

对于OF的值判断:将操作数转换成十进制数,然后运算,得出十进制结果,看是否在寄存器取值范围内,如果超出:OF=1;

对于SF的值判断:执行指令后的结果,最高位是1,SF就是1(负数);最高位是0,SF就是0(正数);

对于PF的值判断:一个一个数吧。或将二进制的所有1相加,得出的十进制结果是偶数-PF=1;否则PF=0.

                     al          CF    OF    SF    ZF    PF

sub al,al     0h/0000 0000b      0     0     0     1     1

结果中含有0个1,故PF=1

mov al,10h    10h/0010 0000b     0     0     0     1     1

mov指令不影响flag寄存器的值,故位值都不变

add al,90h    a0h/1010 0000b     0     0     1     0     1

对于CF:10H+90H=A0H,没有产生进位。CF=0

对于OF:16(10H)-112(90H)=-96,在-128~127范围,没有溢出。OF=0

对于SF:结果是A0H(10100000),最高位是1,SF=1

对于ZF:非0,ZF=0

对于PF:1个数是2(偶数),PF= 1

mov al,80h    80h/1000 0000b     0     0     1     0     1

mov指令不影响flag寄存器的值,故位值都不变

add al,80h    0h/0000 0000b      1     1     0     1     1

对于CF:80H+80H=100H,产生进位。CF=1

对于OF:-128(80H)-128(80H)=-256,不在-128~127范围,溢出。OF=1

对于SF:结果是0H(00000000),最高位是0,SF=0

对于ZF:0,ZF=1

对于PF:1个数是0(偶数),PF= 1

mov al,0fch   0fch/1111 1100b    1     1     0     1     1

mov指令不影响flag寄存器的值,故位值都不变

add al,05h    1h/0000 0001b      1     0     0     0     0

对于CF:fcH+05H=101H,产生进位。CF=1

对于OF:-4(0FCH)+5(80H)=1,在-128~127范围,不溢出。OF=0

对于SF:结果是0H(00000001),最高位是0,SF=0

对于ZF:非0,ZF=0

对于PF:1个数是1(奇数),PF=0

mov al,7dh    7dh/1111 1101b     1     0     0     0     0

mov指令不影响flag寄存器的值,故位值都不变

add al,0bh    88h/1000 1000b     0     1     1     0     1

对于CF:7DH+0BH=88H,不产生进位。CF=0

对于OF:125(7D H)+11(0BH)=136,不在-128~127范围,溢出。OF=1

对于SF:结果是88H(10001000),最高位是1,SF=1

对于ZF:非0,ZF=0

对于PF:1个数是2(偶数),PF=1

11.3答案

(1)补全下面的程序,统计F000:0处32个字节中,大小在[32,128]的数据个数。

     mov ax,0f000h

     mov ds,ax

     mov bx,0      ;ds:bx指向第一个字节

     mov dx,0      ;初始化累加器

     mov cx,32

s:   mov al,[bx]

     cmp al,32     ;和32进行比较

     jb s0         ;如果低于al转到s0,继续循环

     cmp al,128    ;和128进行比较

     ja s0         ;如果高于al转到s0,继续循环

     inc dx

s0:  inc bx

     loop s

程序解释:    jb s0(如果al变量小于32,跳转到s0)

                     ja s0(如果al变量大于128,跳转到s0)

       考虑[32,128]这个数值范围是大于等于32;小于等于128(32<=al<=128)

(2)补全下面的程序,统计F000:0处32个字节中,大小在(32,128)的数据个数。

     mov ax,0f000h

     mov ds,ax

     mov bx,0      ;ds:bx指向第一个字节

     mov dx,0      ;初始化累加器

     mov cx,32

s:   mov al,[bx]

     cmp al,32      ;和32进行比较

     jna s0        ;如果不高于al转到s0,继续循环

     cmp al,128    ;和128进行比较

     jnb s0        ;如果不低于al转到s0,继续循环

     inc dx

s0:  inc bx

     loop s

程序解释:考虑(32.128)的含义是(32<al<128)      

 

检测点11.4

下面指令执行后,(ax)=0045h

mov ax,0            ;(ax)=0

push ax             ;将(ax)入栈

popf                ;将flag寄存器的所有为都初始化为0.因为它们使用的是同一个栈结构。

mov ax,0fff0h       ;(ax)=0fff0H

add ax,0010h        ;执行add后,结果是:(ax)=0000H(作为无符号数,产生进位cf=1),

                    ;作为有符号数没有溢出,of=0;其它zf=1,sf=0,pf=1.我们把这些标志                       ; 位按照顺序组合起来(不能确定的我们不管了):00000xxx010x0101                                  ;我们不能确定的都用X表示。没有使用的用0表示吧             

pushf               ;将flag的值入栈。

pop ax              ;弹栈,(ax)= 00000xxx010x0101

and al,11000101B    ;ax低8位按位与,    010x0101 and 11000101=01000101B=45H

and ah,00001000B    ;ax高8位按位与,00000xxx and 00001000=0000000B=00H

 

程序分析:

1.push和popf使用的是同一个栈结构。

2.考察这个章中所学到的所有标志位的值。cf、sf、of、zf、pf代表的含义,并且对于指令结果后,这些标志位的变化。

3.如果要手动修改这些标志位,我们可以使用按位与和或的方式将ax值修改成我们期望的标志位,然后push,通过popf弹栈到flag中。

 

posted @ 2017-05-21 09:17  筑基2017  阅读(3105)  评论(0编辑  收藏  举报