标志寄存器综述

时间:2022-02-23 01:00:18

转载自: http://www.cnblogs.com/dennisOne/archive/2012/10/23/2736238.html

☞标志寄存器综述

  1. 8086CPU的标志寄存器(flags Register, FR)有16位,其中存储的信息通常被称为程序状态字(PSW),flag寄存器与其他寄存器不同,flag寄存器是按位起作用的。8086的flag寄存器中有CF、PF、ZF、SF、OF、DF标志位。

    标志寄存器综述

  2. 8086的FR的9个标志位

    标志位

    名称

    功能

    ZF

    零标志位(Zero Flag)

    判断结果是否为0。运算结果0,ZF置1,否则置0。

    PF

    奇偶标志位(Parity Flag)

    反映运算结果8位中'1'的个数。'1'的个数为偶数,PF置1,否则置0。

    SF

    符号标志位(Sign Flag)

    反映运算结果的符号。运算结果为负,SF置1,否则置0。

    CF

    进位标志位(Carry Flag)

    反映无符号运算是否产生进位或借位。运算结果的最高有效位向更高位进位或者借位,CF置1,否则置0。

    OF

    溢出标志位(Overflow Flag)

    反映有符号运算是否溢出。运算结果超过了8位或者16位有符号数的表示范围,OF置1,否则置0。

    AF

    辅助进位标志位(Auxiliary Flag)

    在字节操作时低半字节向高半字节进位或借位。字操作时低字节向高字节进位或借位,AF置1,否则置0。

    DF

    方向标志位(Direction Flag)

    决定串处理指令控制每次操作后si、di的增减。df=0,则每次操作后si、di递增,否则递减。

    IF

    中断标志位(Interrupt Flag)

    决定CPU是否响应外部可屏蔽中断请求。IF为1时,CPU允许响应外部的可屏蔽中断请求。

    TF

    陷阱标志位(Trap Flag)

    TF被设置位1时,CPU进入单步模式,所谓单步模式就是CPU在每执行一步指令后都产生一个单步中断。主要用于程序的调试。8086/8088中没有专门用来置位和清零TF的命令。

  3. 影响标志位的指令
    • 在8086CPU的指令集中,诸如add/sub/mul/div/inc/or/and这些逻辑或者算术运算影响FR;而诸如mov/push/pop等传送指令的执行不影响FR。
    • 执行一条指令,要注意这条指令的全部功能(特别是cmp),执行结果对FR的那些标志位造成影响。
    • 某些指令将影响FR中的多个标志位。
  4. 修改标志位的常用方法
    • pushf和popf提供了直接访问标志寄存器的一种方法。

      pushf的功能是将标志寄存器的值压栈;而popf是从栈中弹出数据。比如:

      pushf ; 将FR的值压栈

      pop ax ; (ax)=(FR)

      ; 处理ax

      push ax ; 将修改后的(ax)压栈

      popf ; (FR)=(ax)

    • sub ax, ax 可以将CF设置为0,ZF设置为0。
    • 修改DF

      cld ; 将DF置为0

      std ; 将DF置为1

  5. FR在debug中的表示

    标志寄存器综述

标志位

=1

=0

ZF

ZR[Zero]

NZ[Not Zero]

PF

PE[Parity Even]

PO[Parity Odd]

SF

NG[Negative]

PL[Plus]

CF

CY[Carry]

NC[No Carry]

OF

OV[Overflow]

NV[Not Overflow]

AF

AC[Auxiliary Carry]

NA[No Auxiliary Carry]

DF

DN[Down]

UP[UP]

IF

EI[Enable Interrupt]

DI[Disable Interrupt]

TF

------------------------------

--------------------------------

   

☞从CPU的角度看待指令

以下列指令进行讲解:

mov al, 10000001B

add al, 1

  • CPU在执行add等指令的时候,就已经包含了两种含义(有符号和无符号运算),也将得到同一种信息来记录的两种结果。关键在于我们的程序需要哪一种结果。
  • 通过FR的PSW,我们可以根据需要来看待指令进行的运算。
  • 可以讲add指令进行的运算当做无符号数的运算,那么add指令相当于计算129+1,结果是130(10000010B);也可以将add指令进行的运算当做有符号的运算,那么add指令相当于-127+1,结果也就是-126(10000010B)。

   

☞adb指令和sbb指令

指令

指令格式

功能

示例

带进位加法指令adc

adc op1, op2

op1=op1+op2+CF

adc ax,bx

带借位减法指令sbb

sbb op1, op2

op1=op1-op2-CF

sbb ax,bx

   

Q: 编写一个程序,对两个128位数据进行相加。

 

标志寄存器综述
 1 assume cs:code, ds:code
2
3 data segment
4 db 88h, 88h, 88h, 88h, 88h, 88h, 88h, 88h, 88h, 88h, 88h, 88h, 88h, 88h, 88h, 88h
5 db 11h, 11h, 11h, 11h, 11h, 11h, 11h, 11h, 11h, 11h, 11h, 11h, 11h, 11h, 11h, 11h
6 data ends
7
8 code segment
9 start: mov ax, data
10 mov ds, ax
11 mov si, 0
12 mov di, 8
13
14 mov cx, 8
15
16 call add128
17
18 mov ax, 4c00h
19 int 21h
20
21 add128: ; 子程序开始
22 push ax
23 push cx
24 push si
25 push di
26
27 sub ax, ax ; 将CF置0
28
29 mov cx, 8
30 s: mov ax, [si]
31 adc ax, [di]
32 mov [si], ax
33 inc si ; inc不会影响CF的值;但是add si,2会影响CF的值
34 inc si
35 inc di
36 inc di
37 loop s
38
39 pop di
40 pop si
41 pop cx
42 pop ax
43
44 ret
45 code ends
46 end start
标志寄存器综述

   

☞DF标志和串传递指令

指令

功能

解释

movsb

传送字节单元

mov es:[di], byte ptr ds:[si] ;8086不支持这样的指令,这里示意

如果df=0

inc si

inc di

如果df=1

dec si

dec di

movsw

传送字单元

mov es:[di], word ptr ds:[si] ;8086不支持这样的指令,这里示意

如果df=0

add si, 2

add di, 2

如果df=1

sub si, 2

sub di, 2

rep movsb

串传送

s: movsb

loop s

rep的作用是根据cx的值,重复执行后面的串传送指令。

rep movsw

串传送

s: movsw

loop s

   

☞cmp指令

  1. cmp指令概述

    cmp是比较指令,cmp的功能相当于减法指令,但是不保存结果[猜测:CPU可能使用不能被外界使用的某个寄存器进行暂存?]。cmp指令执行后,将对标志寄存器产生影响。

指令格式

功能

示例

cmp op1, op2

计算op1-op2,但不保存结果,仅仅根据结果对标志寄存器产生影响。

cmp ax, ax
执行指令后:zf=0,pf=1,sf=0,cf=0,of=0

   

  1. 和sub指令一样,CPU在执行cmp指令时,也包含两种含义:进行无符号数和有符号数运算。
  2. cmp ax, bx当做"无符号数运算"的含义[根据zf和cf进行解释]

    标志寄存器综述

    反过来:

    标志寄存器综述

    根据无符号数的比较结果进行转移的条件转移指令(短转移)的原理就是基于上表。

    标志寄存器综述

  3. cmp ax, bx当做"有符号数运算"的含义[根据zf/sf/of进行解释]

    【公理】:进行有符号数运算时,如果发生溢出(of=1),说明实际运算结果与逻辑运算结果不等;如果没有溢出(of=0),说明实际运算结果与逻辑运算结果一致。

    标志寄存器综述

   

☞cmp指令和条件转移指令的联合使用

标志寄存器综述

   

标志寄存器综述

总结:题(1)中"等于"和题目(2)中"大于"需要进行特别处理,所以应该讲"不等于"和"不大于"的直接跳出,这样可以使得程序更加简洁。