8086汇编-标志寄存器
9unk Lv5

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

  1. 用来存储相关指令的某些执行结果
  2. 用来为 CPU 执行相关指令提供行为依据
  3. 用来控制 CPU 相关的工作方式

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

8086CPU 的 flag 寄存器的结构如下图所示:

139.png

flag 寄存器的 1、3、5、12、13、14、15 位在 8086CPU 中没有使用,不具有任何含义。而 0、2、4、6、7、8、9、10、11 位都具有特殊的含义。

在 debug 调试器中各标志位的状态如下:
图片

状态标志位

CF 标志位

flag 的第 0 位是 CF 位,进位标志位,用来记录无符号运算的结果。当逻辑运算,出现超出寄存器大小的范围进位时 CF 位置 1,或者向超出寄存器大小范围进行借位时 CF 位置 1。

例1(进位):

1
2
3
4
al=FF=0(进位值) 1(最高有效位)111 1111
al+1=1(进位值) 1111 1111

这里 al+1 的结果多了超出 al 寄存器范围的1,此时CF位置1

图片

例2(借位):

1
2
al=5=0(借位值) 0101
al-6=1(借位值) 0101-6=FF

图片

这里的进位或者借位,就可以当成 CF 位,当两个数相加或相减的操作数超过寄存器的大小,CF 位就会置 1。

PF 标志位

flag 的第 2 位是 PF,奇偶标志位。它记录了相关指令执行后,其结果的所有 bit 位中 1 的个数是否为偶数。如果 1 的个数偶数,pf=1,如果为奇数,那么 pf=0。

例1:

1
2
mov al,1
add al,10

执行后,结果为 00010001B,其中有 2(偶数)个 1,则 pf=1;

图片

例2:

1
sub al,10

执行后,结果为 00000001B,其中有 1(奇数)个 1,则 pf=0。

图片

PF位通常用来做校验的,校验数据传输的结果是否正确,或者校验数据拷贝的结果是否正确。例如:传输的时候有 4 个 1,但是接收的时候是3 个 1,这个时候就说明你传输的结果错了。

ZF 标志

flag 的第 6 位是 ZF,零标志位。它记录相关指令执行后,其结果是否为 0。结果为 0,那么 zf=1;如果结果不为 0,那么 zf=0。

例1:

1
2
mov ax,1
sub ax,1

执行后,结果为 0,则 zf=1,表示 “结果是 0”

6

例2:

1
2
mov ax,2
sub ax,1

执行后,结果不为0,则 zf=0,表示 “结果非 0”

7

在 8086CPU 的指令集中,大多数逻辑运算指令的执行是影响标志寄存器的,大多数数据转移指令的执行对标志寄存器没有影响。

SF 标志

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

在计算机中我们可以人为把一个数据看作是有符号数,也可以看成是无符号数。当把一个数看作有符号数,其最高位就是符号位(不包括在数值运算中)

例如:

1
2
0000 0001B,有符号数+1;
1000 0001B,有符号数-127。

例1(3+4):

1
2
mov al,3
add al,4

计算结果:3+4=7

两个正数相加,最高位是 0,SF 置 0

10

例2(-1-1):

1
2
mov al,ff
add al,ff

计算结果:-1+(-1)=-2(FE)
当 2 个负数相加最高位是1,所以 SF 置 1 。同时又因为这两个值相加导致出现溢出,所以 CF 位也置 1 。我们可以得出有符号数的运算,是会影响到无符号数运算的 CF 标志位。那这个会对无符号数运算有影响吗?

9

SF位和CF位同时改变对计算结果没有影响,SF 位是符号位只表示这个值是正数还是负数,不会影响结果。如果我们做的是无符号计算,对于我们来说 SF 位如何改动都是没有意义的。

OF 标志

flag 的第 11 位是 OF,溢出标志位(针对有符号数的进位运算)。如果有符号数运算结果超出机器所能表达的范围,将产生溢出,这里的溢出只是对有符号数运算而言。对于 8 位的有符号数据,机器所能表示的范围是 -128127,对于 16 位有符号数据,机器所能表示的范围是 -3276823767。

例1(100+100):

1
2
mov al,64
add al,64

计算结果:100+100=00C8

al 最大有符号数 127(7F),当 2 个正数相加得到的结果是负数,那就说明计算结果超过该寄存器有符号数的存储范围 OF 置 1 ,否则 OF 为 0

11

OF位和CF位同样互不影响,你要计算有符号数的进位,就看OF位;要计算无符号数的进位就看 CF 位。计算的时候别把这两个位搞混了,你想计算有符号数的进位,但是用的是CF位来计算,那就出问题了。

控制标志位

TF 位

TF 位用于单步执行,调试器中的 T 命令就是单步执行。默认情况下 TF 位是为 0 的,也就是说 IP指针寄存器自动加1,程序会自动往下一条一条地执行指令。当 TF 置 1 时,就是单步执行,调试器里面的单步调试,就是 CPU 里面已经设置好了 TF 位,允许单步执行,所以调试器才可以单步执行。

IF 位

IF 位默认状态是置 1 的,这个是中断标志位。中断可以理解为高级语言中的函数,其功能是控制计算机的外设数据的输入/输出。IF 置 1 表示开中断,IF 置 0 表示关中断。如果 IF 位置 0 了,那么外设就无法使用了,你无法通过外设向计算机中输入任何的数据。

DF 位

DF 位默认状态是 0 ,是方向标志位。表示数据读取/拷贝是从左向右拷贝数据,还是从右向左拷贝数据。DF 置 0 是从左往右,即从低地址向高地址读取/拷贝数据。DF 置 1 是则相反。

JCC 指令

JCC 指令是根据状态标志位,进行跳转的指令,它主要分为 3 组

一组是直接判断状态标志位
13
12

一组是无符号数的JCC指令
14

一组是有符号数的JCC指令
15

代码练习

  1. JB.asm

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    ;程序名:jb.asm
    ;功能:显示一个字符串
    ;===========================
    assume cs:code,ds:data

    data segment
    ;8086汇编中的变量定义
    ;在数据段偏移地址0处,定义一个以字节为单位的string变量
    ;为其分配 22 个字节大小的内存空间,并将数值初始化为相应字符
    string db "hello ,welcome to JB!","$"

    ;在数据段偏移地址 number 处,定义一个以字节为单位的 number 变量,
    ;为其分配 6 个字节大小的内存空间,并将数值初始化为 "1,2,3,4,5,6"

    number db 1,2,3,4,5,6
    data ends

    code segment
    start:
    mov ax,data
    mov ds,ax
    ;jb(jmp below)无符号数跳转,[si] < [si+1] CF=0
    mov si,offset number
    mov al,byte ptr ds:[si]
    cmp al,[si+1] ;使用减法运算,功能与 sub 指令一样,区别在于该指令不会改变寄存器中的值
    jb str
    ;
    mov ax,4c00h
    int 21h
    ;
    str:
    mov dx,offset string
    mov ah,9
    int 21h
    mov ax,4c00h
    int 21h
    code ends
    end start
  2. JL.asm

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    ;程序名:JL.asm
    ;功能:显示一个字符串
    ;===========================
    assume cs:code,ds:data

    data segment
    string db "hello ,welcome to JL!","$"
    number db 1,2,3,4,5,6
    data ends

    code segment
    start:
    mov ax,data
    mov ds,ax
    ;jL(jmp less)有符号数跳转,[si] < [si+1] SF xor OF=1 跳转
    mov si,offset number
    mov al,-1
    cmp al,1 ;有符号数 -1<1
    ;jb str ;用无符号数跳转,程序出现错误
    jl str
    ;
    mov ax,4c00h
    int 21h
    ;
    str:
    mov dx,offset string
    mov ah,9
    int 21h
    mov ax,4c00h
    int 21h
    code ends
    end start
  3. je.asm

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    ;程序名:je.asm
    ;功能:显示一个字符串
    ;===========================
    assume cs:code,ds:data

    data segment
    string db "hello ,welcome to jE!",0dh,0ah,24h
    number db 1,2,3,4,5,6
    data ends

    code segment
    start:
    mov ax,data
    mov ds,ax
    ;je(jmp equal)相等就跳转,[si] == [si] ZF=1
    mov si,offset number
    mov al,byte ptr ds:[si]
    cmp al,[si]
    je str
    ;
    mov ax,4c00h
    int 21h
    str:
    mov dx,offset string
    mov ah,9
    int 21h
    mov ax,4c00h
    int 21h
    code ends
    end start

注意:你要进行有符号数运算,就用有符号数跳转;无符号数运算,用无符号数跳转。无符号数跳转中含有B(Below)和A(Above),有符号数跳转中含有L(Less)和G(greater)。如有其他问题,自己修改代码进行验证。

跳转指令太多,有映像就行,不需要死记,如果忘了就去查,这些指令用多了就记住了。

  • 本文标题:8086汇编-标志寄存器
  • 本文作者:9unk
  • 创建时间:2022-04-17 01:07:13
  • 本文链接:https://9unkk.github.io/2022/04/17/8086-hui-bian-biao-zhi-ji-cun-qi/
  • 版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!