zoukankan      html  css  js  c++  java
  • 8086标志寄存器

    CPU内部的寄存器中,有一种特殊的寄存器(对于不同的机器,个数和结构都有可能不同)具有以下三个功能:

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

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

    标志寄存器与其他寄存器不一样,其他寄存器是用来放数据的,都是整个寄存器具有一个含义,而标志寄存器是按位起作用的。

    8086中的标志寄存器的结构如下图所示:

    其中1、3、4、12、13、14、15位在8086中没有使用。另外对于有确切含义的每一位,我们称为标志位

    ZF标志

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

    比如指令:

    mov ax, 1
    sub ax, 1
    

    执行后,ax的结果为0,所以zf=1

    再比如:

    mov ax, 2
    sub ax, 1
    

    执行后,ax的结果不为0,所以zf=0

    在这里,有一点需要注意:在8086的指令集中,有的指令的执行是影响标志位的,比如add、sub、mul、div、inc、or、and等,它们大都是运算指令(进行逻辑或算数运算);有的指令的执行对标志寄存器没有影响,比如mov、push、pop等,它们大都是传送指令。

    PF标志

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

    比如指令:

    mov al, 1
    add al, 10
    

    执行后,al为00001011B,其中有3个1,所以pf=0

    再比如:

    mov al, 1
    or al, 2
    

    执行后结果为00000011B,其中有2个1,所以pf=1

    SF标志

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

    这里要明确一点,在计算机中,通常用补码来表示有符号的数据,计算机中的一个数据既可以看作有符号数,也可以看作无符号数。不管我们如何看待,当CPU在进行运算的时候,就已经包含了两种含义,也将的到同一种信息来记录的两种结果。关键在于我们的程序需要那一种。

    SF标志,是CPU对有符号数运算结果一种记录。如果我们将数据当作无符号数来运算,SF标志位则没有意义,虽然计算过程中影响了他的值。

    我个人在这里的更简单写的理解是计算后结果的最高位是否为1,为1,这sf=1,否则,sf=0

    比如指令:

    mov al, 100000001B
    add al, 1
    

    执行后结果为10000010B,sf=1,表示如果进行的是有符号运算的话,则结果为负

    再比如

    mov al, 10000001B
    add al, 01111111B
    

    执行后,结果为0,sf=0,表示,如果进行的是有符号运算,这结果为非负

    CF标志

    标志寄存器的第0为是CF,仅为标志位。一般情况下,在进行 无符号 运算的时候,它记录了运算结果的最高有效位向更高有效位的进位,或从更高有效位的借位。

    比如指令:

    mov al, 98H
    add al, al  ; 执行后(al)=30H, CF=1, 产生进位
    add al, al  ; 执行后(al)=60H, CF=0, 没有进位,或者说进位为0
    

    再比如:

    mov al, 97H
    sub al, 98H  ; 执行后(al)=FFH, CF=1, 产生借位
    sub al, al   ; 执行后(al)=0, CF=0, 借位为0
    

    OF标志

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

    {% note success %} 这里一定要注意的是CF和OF的区别,CF是对无符号数运算有意义的标志位,而OF是对有符号数运算有意义的标志位。 它们之间没有任何关系 {% endnote %}

    比如指令:

    mov al, 98
    add al, 99
    

    执行后,of=1,发生溢出,没有进位

    再比如:

    mov al, 0F0H
    add al, 78H
    

    执行后:of=0,没有溢出

    DF标志

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

    df=0,每次操作后si、di递增

    df=1,每次操作后si、di递减

    例如串传送指令movsb

    • 格式:movsb

    • 功能:执行下面几步操作:1、((es) x 16 + (di)) = ((ds) x 16 + (si)) 2、如果df=0,(si)=(si)+1, (di)=(di)+1。如果df=1,则(si)=(si)-1, (di)=(di)-1

    另外还有movsw,这时候就是一次传送一个字了,相应的si和di的+1-1也就变更成了+2-2

    一般,movsbmovsw一般配合指令rep指令使用,如rep movsb, 相当于

    s: movsb  ; 当然啦,在此之前要先设置cx寄存器
       loop s
    

    adc、sbb、cmp、pushf和popf指令

    再没有标志寄存器的时候,我们进行加减运算最多只能进行16位的加减运算,这在实际的应用中显然是不够的,那么有了标志寄存器,在结合adcsbb指令,我们就可以进行任意多位的数的加减法了

    adc指令

    adc是带进位的加法指令,它利用了CF上记录的进位值

    • 指令格式:adc 操作对象1,操作对象2
    • 功能: 操作对象1 = 操作对象1 + 操作对象2 + CF

    比如:计算1EF000H + 201000H,结果放在ax(高16位)和bx(低16位)中:

    mov ax, 001EH
    mov bx, 0F000H
    add bx, 1000H
    adc ax, 0020H
    

    更多位数的数相加和以上同理

    sbb指令

    sbb是借位减法指令,它利用了CF位上记录的借位值

    • 指令格式:sbb 操作对象1,操作对象2
    • 功能:操作对象1 = 操作对象1 - 操作对象2 - CF

    比如:计算003E1000H - 00202000H,结果保存在ax,bx中

    mov bx, 1000H
    mov ax, 003EH
    sub bx, 2000H
    sbb ax, 0020H
    

    cmp指令

    cmp是比较指令,功能相当于减法指令,只是不保存结果。执行后,对标志寄存器产生影响

    • cmp指令格式:cmp 操作对象1,操作对象2
    • 功能:计算操作对象1 - 操作对象2,但不保存结果

    经过cmp计算后,我们就可以用jejnejbjnbjajna指令进行跳转了。

    因为比较复杂,在这里就不具体说实现的细节了,具体在更。

    pushf和popf指令

    pushf的功能是将标志寄存器的值压栈,而popf是从栈中弹出数据送入标志寄存器

    这两个指令为直接访问寄存器提供了一种方法


    在这里,我们讨论了六种寄存器,另外还有IF,TF,和AF没有讨论,具体再更

  • 相关阅读:
    组合和封装
    面向对象之继承与派生
    实例化产生对象和绑定关系
    面向对象程序设计和类
    常用模块(hashlib、suprocess、configparser)
    常用模块re模块(正则表达式)
    包及常用模块(time、datetime、random、sys)
    python内置函数大全
    软件开发规范及常用模块
    [NOI Online 提高组]序列 (并查集+二分图判定)
  • 原文地址:https://www.cnblogs.com/tcctw/p/10662965.html
Copyright © 2011-2022 走看看