汇编语言:标志寄存器ZF, PF, SF, CF, OF, DF, IF, AF 和 pushf, popf 指令

        CPU内部的寄存器中,一种特殊的寄存器(对于不同的CPU,个数和结构可能都不同),具有以下3种作用。

(1)用来存储相关指令的某些执行结果

(2)用来为CPU执行相关指令提供行为依据

(3)用来控制CPU的相关工作方式

        这种特殊的寄存器在8086CPU中,被称为标志寄存器,8086CPU的标志寄存器有16位,其中存储的信息通常被称为程序状态字(Program Status Word,PSW)。8086CPU的标志寄存器结构图如下:

其中,1、3、5、12、13、14、15位在8086CPU没有使用,不具有任何含义。

tips:

        在debug中,对标志位的表示按照显示顺序如下:

标志位值OFDFIFSFZFAFPFCF
0NVUPDIPLNZNCPONC
1OVDNEINGZRACPECY

OF(Overflow Flag):溢出标志位,一般情况下,它记录了有符号运算的结果是否发生了溢出。

NV(No Overflow)= 0:没有溢出

OV(Overflow)= 1:溢出

DF(Direction Flag):方向标志位,在串行处理指令中,控制每次操作后si、di的增减。

df = UP = 0:每次操作后si、di递增,即:(si) = (si) + 1; (di) = (di) + 1;

df = DN(down)= 1:每次操作后si、di递减,即:(si) = (si) - 1; (di) = (di) - 1;

IF(Interrupt Flag):中断标志位。它用来控制8086是否允许接收外部中断请求。若IF=1,8086能响应外部中断,反之则屏蔽外部中断。
DI(Disabled Interrupt)= 0:不允许中断
EI (Enable Interrupt)= 1:允许中断

SF(Signed Flag):符号标志位,记录相关指令执行后,其结果是否为负,如果结果为负,则sf = 1,如果结果为非负,则sf = 0。

NG(Negative,负数)= 1:结果为负

PL(Plus,正数)= 0:结果为正

ZF(Zero Flag):零标志位,记录相关指令执行后,其结果是否为0,如果结果为0,则zf = 1,如果结果不为0,则zf = 0。

ZR(Zero)= 1:结果为0

NZ(Not Zero)= 0:结果不为0

AF(Auxiliary carray flag):辅助进位标志位,运算过程中看最后四位,不论长度为多少,最后四位向前有进位或者借位,AF = 1,否则AF = 0

AC(Auxiliary Carry)= 1:有辅助进位

NA(Not Auxiliary carry)= 0:没有辅助进位

PF(Parity Flag):奇偶标志位,记录相关指令执行后,其结果所有的位中 1 的个数是否为偶数,如果 1 的个数为偶数,则pf = 1,如果1的个数为奇数,则pf = 0。

PE(Parity Even,偶数)= 1:结果有偶数个1

PO(Parity Odd,奇数)= 0:结果有奇数个1

CF(Carry Flag):进位标志位,它一般记录了在做加法运算时,从最高有效位向更高位进位了,或做减法运算时,最高有效位向更高位借位了。

CY(Carried Yes)= 1:有进位或有借位

NC(Not Carried)= 0:没进位或没借位

1. ZF 标志(Zero Flag)

        标志寄存器的第6位是 zf,零标志位,记录相关指令执行后,其结果是否为0,如果结果为0,则zf = 1,如果结果不为0,则zf = 0。

比如

mov ax, 1

sub ax, 1

指令执行后,结果为0,则zf = 1。

mov ax, 2

sub ax, 1

指令执行后,结果不为0,则zf = 0

tips:

        在8086指令集中,有的指令的执行是影响标志寄存器的,比如:add,sub,mul,div,and,or,inc,dec等,它们大都是运算指令(进行算术运算或逻辑运算);有的指令的执行是不影响标志寄存器的,比如:mov,push,pop等,它们大都是传送指令。我们在使用一条指令的时候,要注意这条指令的全部功能,包括执行结果对标志寄存器的哪些标志位会产生影响。

2. PF 标志(Parity Flag)

        标志寄存器的第2位是 pf,奇偶标志位,记录相关指令执行后,其结果所有的位中 1 的个数是否为偶数,如果 1 的个数为偶数,则pf = 1,如果1的个数为奇数,则pf = 0。

比如

mov ax, 1

sub ax, 1

指令执行后,结果为0,所有的位中 1 的个数为 0 (偶数)个,则pf = 1。

mov ax, 2

sub ax, 1

指令执行后,结果为1,所有的位中 1 的个数为 1 (奇数)个,则pf = 0

3. SF 标志(Signed Flag)

        标志寄存器的第7位是 sf,符号标志位,记录相关指令执行后,其结果是否为负,如果结果为负,则sf = 1,如果结果为非负,则sf = 0。

        计算机中,通常用补码来表示有符号数,在计算机中,一个数可以看作是有符号数,也可以看成无符号数。

比如

0000 0001B,可以看成无符号数 1,也可以看成有符号数 +1

1000 0001B,可以看成无符号数 129,也可以看成有符号数 -127(原码:对补码再做一次求补码操作得到一个用补码形式表示的数的原码,补码 = 反码 + 1,补码:1000 0001B ,原码 = 反码 + 1 = 1111 1110B + 1 = 1111 1111b = -127)。

        所以,对于同一个二进制数,计算机可以将它当作无符号数据来运算,也可以当作有符号数据来运算。

比如

mov al, 10000001b

add al, 1

结果为:10000010b

        可以将 add 指令进行的运算当作无符号数的运算,那么 add 指令相当于计算 129 + 1,结果 = 130 (1000 0010b);也可以将 add 指令进行的运算当作有符号数的运算,那么 add 指令相当于计算 -127 + 1,结果 = -126(1000 0010b)

        所以,SF标志,就是CPU对有符号运算结果的一种记录,它记录了数据的正负。在我们数据当作有符号数来运算的时候,可以通过它来得到结果的正负;如果我们将数据当作无符号来运算,SF 的值则没有意义,虽然相关指令影响了它的值。也就是说,CPU 在进行 add 等指令时,是必然会影响到 SF 标志的值的。至于我们需不需要这种影响,那就看我们如何看待指令所进行的运算了。

比如

mov al, 10000001b

add al, 1

指令执行后,结果为:10000010b,sf = 1,表示:如果指令进行的是有符号数运算,那么结果为负,如果指令进行的是无符号数运算,虽然 sf = 1,但没有意义。

比如

mov al, 10000001b

add al, 01111111b

指令执行后,结果为:0,sf = 0,表示:如果指令进行的是有符号数运算,那么结果为非负。

        有些指令的执行会影响标志寄存器中的多个标记位,比如:sub al, al,执行后,标志寄存器中的 zf = 1,pf = 1,sf = 0

检测点11.1

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

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

mov al, 1        ZF = 1, PF = 1, SF = 0(传送指令不影响标志寄存器的状态)

push ax          ZF = 1, PF = 1, SF = 0(传送指令不影响标志寄存器的状态)

pop bx           ZF = 1, PF = 1, SF = 0(传送指令不影响标志寄存器的状态)

add al, bl       ZF = 0, PF = 0, SF = 0(结果 = 0000 0010b,不为0,奇数个1,符号位为0)

add al, 10      ZF = 0, PF = 1, SF = 0(结果 = 0000 1100b,不为0,偶数个1,符号位为0)

mul al            ZF = 0, PF = 1, SF = 0 (结果 ax = 0000 0000 1001 0000b, 不为0, 偶数个1, 两个相同的数相乘结果肯定为正数,所以SF = 0)

在debug中,

4. CF 标志(Carry Flag)

        标志寄存器的第0位是 cf,进位标志位,它一般记录了在做加法运算时,从最高有效位向更高位进位了,或做减法运算时,最高有效位向更高位借位了。

CY(Carried Yes)= 1:有进位或有借位

NC(Not Carried)= 0:没进位或没借位

        对于位数为N的无符号数来说,其对应的二进制信息的最高位,即第N-1位,就是它的最高位,而假想存在的第N位,就是相当于最高有效位的更高位,如下图所示。

        

我们知道,当两个数据相加时,有可能从最高有效位向更高位产生进位,8086CPU的标志寄存器的CF位就是来记录这个进位值的。

比如

mov al, 98h

add al, al        ;该指令执行后,(al) = 30h, CF = 1

add al, al        ;该指令执行后,(al) = 60h, CF = 0

而当两个数进行减法运算时,有可能向更高位借位,8086CPU的标志寄存器的CF位记录了这个借位值。

比如

mov al, 97h

sub al, 98h        ;该指令执行后,(al) = ffh, 向更高位借位了,CF = 1

sub al, al            ;该指令执行后,(al) = 0h, CF = 0

5. OF 标志(Overflow Flag)

        标志寄存器的第11位是 of,溢出标志位,一般情况下,它记录了有符号运算的结果是否发生了溢出。

        在进行有符号数运算时,如果超过了机器所能表示的范围称为溢出。比如,8位有符号数的范围:-128 ~ 127。16位有符号数的范围:-32768 ~ 32767。

示例:

8位有符号数

mov al, 100

add al, 29        ;该指令执行后,(al) = 01h,溢出了,OF = 1

示例:

8位有符号数

mov al, -100

sub al, 29        ;该指令执行后,(al) = 7fh,溢出了,OF = 1

tips:

-100 的补码:1001 1100b = 9ch

-29 的补码:1110 0011b = E3h

检测点11.2

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

sub al, al        ;ZF = 1,PF = 1,SF = 0,CF = 0,OF = 0(结果al = 0)

mov al, 10h    ;ZF = 1,PF = 1,SF = 0,CF = 0,OF = 0(传送指令,不影响标志寄存器的状态)

add al, 90h     ;ZF = 0,PF = 1,SF = 1,CF = 0,OF = 0(对于无符号数来说,0001 0000B + 1001 0000B = 1010 0000B,没有向更高位进位,所以 CF = 0,对于有符号数来说,0001 0000B + 1001 0000B = 1010 0000B = -96,实际上换成十进制是 16 + (-112) = - 96,没有溢出,所以 OF = 0,结果不为0,所以 ZF = 0,结果有2(偶数)个1,所以 PF = 1)

mov al, 80h     ;ZF = 0,PF = 1,SF = 1,CF = 0,OF = 0(传送指令,不影响标志寄存器的状态)

add al, 80h      ;ZF = 1,PF = 1,SF = 0,CF = 1,OF = 1(对于无符号来说,1000 0000B + 1000 0000B = 0000 0000B = 0,有向更高位进位,所以 CF = 1,对于有符号数,1000 0000B + 1000 0000B = 0000 0000B = 0,,实际上换成十进制是 -128 - 128 = -256,溢出了,所以,OF = 1,结果为0,所以 ZF = 1,结果有 0 (偶数)个1,所以 PF = 1,结果的符号位为0,所以 SF = 0)

mov al, 0FCh   ;ZF = 1,PF = 1,SF = 0,CF = 1,OF = 1(传送指令,不影响标志寄存器的状态)

add al, 05h       ;ZF = 0,PF = 0,SF = 0,CF = 1,OF = 0(对于无符号数来说,1111 1100B + 0000 0101B = 0000 0001B,有向更高位进位,所以 CF = 1,对于有符号数,1111 1100B + 0000 0101B = 10000 0001B = 0000 0001B = 1,实际上换成十进制是:-4 + 5 = 1,没有溢出,所以 OF = 0,结果为1,所以 ZF = 0,结果有1(奇数)个1,所以 PF = 0,结果的符号位为0,所以 SF = 0)

mov al, 7Dh      ;ZF = 0,PF = 0,SF = 0,CF = 1,OF = 0(传送指令,不影响标志寄存器的状态)

add al, 0Bh      ;ZF = 0, PF = 1,SF = 1,CF = 0,OF = 1(对于无符号数来说,0111 1101b + 0000 1011b = 1000 1000b,没向更高位进位,所以 CF = 0,对于有符号数来说,0111 1101b + 0000 1011b = 1000 1000b = -8,实际上换成十进制是 125 + 11 = 136,溢出了,所以 OF = 1,结果为 -8,所以 ZF = 0,结果有 2(偶数)个1,所以 PF = 1,结果的符号位为1,所以 SF = 1)

6. DF(Direction Flag)

        标志寄存器的第10位是 df,方向标志位,在串行处理指令中,控制每次操作后si、di的增减。

df = UP = 0:每次操作后si、di递增,即:(si) = (si) + 1; (di) = (di) + 1;

df = DN(down)= 1:每次操作后si、di递减,即:(si) = (si) - 1; (di) = (di) - 1;

7. pushf 和 popf 指令

        pushf 指令的功能是将标志寄存器的值压入栈中。

        popf 指令的功能是从栈顶弹出数据,送入标志寄存器中。

注:本文是学习笔记

《汇编语言(第4版)》- 王爽

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值