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

    标志寄存器(8086CPU)

    作用

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

    大小

    标志寄存器有16位

    使用方式

    标志寄存器是按位起作用,也就是说每一个位都有专门的含义,记录特定的i西南西

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

    ZF标志,在第6位,结果为0则为1,否则为0

    zf (Zero Flag) 是零标志位,在第6位;它记录相关指令执行后,其结果是否为0,如果为0,那么zf = 1;否则zf = 0

    例如

    mov ax, 1
    sum ax, 1
    

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

    mov ax, 2
    sum ax, 1
    

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

    注意

    在指令执行的过程中,有些指令对标志寄存器有影响,比如:add、sum、mul、div、inc、or、and等,他们大都是运算指令;而有些指令对标志寄存器没有影响,比如:mov、push、pop等,他们大都是传送指令。在使用一条指令的时候,要注意这条指令的全部功能,其中包括,执行结果对标志寄存器的哪些标志位产生了影响。

    PF标志,在第2位,结果中1的个数为偶数则为1,否则为0

    pf( Parity Flag)表示奇偶标志位,在第2位;他记录的是相关指令执行后,如果所有的bit位中1的个数是否为偶数。如果1的个数位偶数,pf = 1,如果为奇数,那么pf = 0

    例如:

    mov al, 1
    add al, 10
    

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

    mov al, 1
    or al, 2
    

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

    SF 标志,在第7位,结果为负则为1,否则为0;有符号运算有效

    sf(Symbol Flag)表示符号标志位,在第7位;它记录相关指令执行后,其结果是否为负。如果为负,则sf = 1;如果非负,sf = 0

    通常CPU计算的时候有两种方式,一种是有符号的计算,一种是无符号的计算。

    SF标志,就是CPU对有符号数运算结果的一种记录,他记录数据的正负。

    如果我们将数据进行无符号运算,SF的值则没有意义,虽然相关指令影响了他的值

    例子:

    mov al, 10000001B
    add al, 1
    

    执行后,结果为10000010Bsf = 1,表示:如果指令进行是有符号运算,那么结果为负

    mov al, 10000001B
    add al, 01111111B
    

    执行后,结果为0,sf = 0;表示:如果指令记性的是有符号数运算,那么结果为0

    CF标志,在第0位,存储进位或借位的值

    cf(Carry Flag)表示进位标志位,在第0位。在进行无符号运算的时候,他记录了运算结果的最高有效位向更高位的进位值,或从更高位的借位值

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

    ​ 我们都知道,在两个数相加的时候,会往更高的位进位;比如98H + 98H,将产生进位。由于这个进位值在8位数中无法进行报错。我之前认为这个数就丢失了。其实CPU在运算的时候,并不丢弃这个值,而是记录在CF标志位上面。

    例如

    mov al, 98H
    add al, al
    

    执行后:(al) = 30H, CF = 1,CF 记录了从最高有效位向更高位的进位值

    再次执行add al, al

    执行后:(al) = 60H, CF = 0, CF记录了从最高有效位向更高位的进位值

    而在做减法的时候,有可能向更高位借位;比如,两个8位数据97H - 98H,将产生借位。借位后相当于计算197H-98H;CF来记录这个借位值,例如下面的指令

    mov al, 97H
    sub al, 98H ; 执行后:(al) = FFH, CF=1, CF记录了向更高位的借位值
    sum al, al  ; 执行后:(al) = 0, CF = 0, CF 记录了向更高位的借位值
    

    OF标志,在第11位,结果溢出则为1,否则为0;没理解透彻

    of( Overflow Flag)表示溢出标志位,在第11位。它记录了有符号数运算的结果是否产生了溢出,如果产生了溢出,of = 1;如果没有,OF = 0

    CPU在执行add等指令的时候,就包含了两种含义:

    1. 无符号数运算
    2. 有符号数运算

    对于无符号数运算,CPU用CF来记录是否产生了进位;对于有符号数运算,CPU用OF来记录是否产生了溢出。当然还要用SF来记录结果的符号。对于无符号数运算98+99没有进位,CF = 0;对于有符号数运算,98 + 99发生溢出,OF= 1

    mov al, 0F0H
    add al, 88H
    

    add指令执行后:CF = 1, OF= 1。对于无符号数运算,0F0 + 88H有进位CF= 1, 对于有符号运算,0F0H + 88H发生溢出,OF = 1

    mov al, 0F0H
    add al, 78H
    

    add指令执行后:CF = 1, OF = 0。对于无符号运算,0F0 + 78H有进位,CF = 1;对于有符号运算,0F0 + 78H不会发生溢出, OF = 0

    每一个有符号数,似乎都对应着一个无符号数,我们如何知道CPU在执行运算指令的时候,进行的是有符号运算还是无符号运算呢??????????????

    DF标志

    df( Direction Flag), 第10位。在串处理指令中, 控制每次操作后si、di的递减

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

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

    通过cld和std指令来进行设置DF的标志

    然后用req movsb/movsw进行复制数据

    串传送指令movsb

    ds:si指向的内存单元中的字节送入es:di中,然后根据标志寄存器df位的值,将sidi递增或递减

    格式:movsb

    功能:执行movsb指令相当于执行下面几步操作

    1. ((es) * 16 + (di)) = ((ds) * 16 + (si))
    2. 如果df = 0则:(si) = (si) + 1, (di) = (di) + 1
    3. 如果df = 1则:(si) = (si) - 1(di) = (di) - 1

    movsb的功能可以这样描述mov es:[di], byte ptr ds:[si],但是8086CPU没有这样的指令。

    如果df = 0

    inc si
    inc di
    

    如果df = 1

    dec si
    dec di
    

    串传送指令movsw

    movsw功能是将ds:si指向的内存单元中的字节送入es:di中,然后根据标志寄存器df位的值,将sidi递增2或递减2

    movsw的功能可以这样描述mov es:[di]. word ptr es:[si] 8086不支持这样的指令,这里只是描述

    如果df = 0

    add si, 2
    add di, 2
    

    如果df = 1

    sub si, 2
    sub di, 2
    

    movsb和movsw进行的是串传送操作中的一个步骤,一般来说,movsbmovsw都和req配合使用,格式如下

    reg movsb

    用汇编语法来描述req movsb的功能是:

    s:
      movsb
      loop s
    

    cld和std设置DF标志位

    cld 指令:将标志寄存器df位,置0

    std 指令:将标志寄存器的df位,置1

    adc 指令,带位加法指令,用于计算特别大的数据

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

    指令格式:abc 操作对象1, 操作对象了

    功能:操作对象1 = 操作对象1 + 操作对象2 + CF

    比如指令:adc ax, bx实现的功能就是:(ax) = (ax) + (bx) + CF

    例:

    mov ax, 2
    mov bx, 1
    sub bx, ax
    adc ax, 1
    

    执行后,(ax) = 4。adc执行时,相当于计算:(ax) + 1 + CF = 2 + 1 + 1 = 4

    mov ax, 1
    add ax, ax
    adc ax, 3
    

    执行后,(ax = 5). adc执行时,相当于计算: (ax) + 3 + CF = 2 + 3 + 0 = 5

    mov al, 98H
    add al, al
    adc al, 3
    

    执行后,(al) = 34H。adc执行时,相当于计算:(al) + 3 + CF = 30H + 3 + 1 = 34H

    可以看出,adc指令比add指令多加了一个CF位的值。

    为啥要加呢?为啥要有这样一条指令呢? 看一下两个数据0198H和0183H

    image-20191116100944518

    可以看出加法是分两步进行的

    1. 低位相加
    2. 高位相加再加上低位相加产生的进位值

    下面的指令和add ax, bx具有相同的值

    add al, bl
    adc ah, bh
    

    CPU提供adc指令的目的,就是来进行加法的第二步运算的,比如我们需要计算特别大的数据的时候可以采用这种方式

    sbb 指令, 带借位减法指令,用于运算特别大的数据

    带位减法指令,利用CF位上记录的借位值

    指令格式: sbb 操作对象1,操作对象2
    功能:操作对象1 = 操作对象1 - 操作对象2 - CF
    比如指令sbb ax, bx 实现的功能是:(ax) = (ax) - (bx) - CF

    cmp指令,这个玩意有点复杂(P234, 11.8)

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

    指令格式: cmp 操作对象1,操作对象2
    功能:计算操作对象1-操作对象2但并不保存结果,仅仅根据计算结果对标志寄存器进行设置。

    比如,指令cmp ax, ax(ax)-(ax)的运算,结果为0,但并不在ax中保存,仅仅影响flag的想改给为。指令执行后:zf = 1, pf = 1, sf = 0, cf = 0, of = 0

    下面的指令:

    mov ax, 8
    mov bx, 3
    cmp ax, bx
    

    执行后:(ax) = 8, zf = 0, pf = 1, sf = 0, cf = 0, of = 0

    其实我们通过cmp指令执行后,相关标志位的值就可以看出比较的结果

    cmp ax, bx

    如果(ax) = (bx)(ax) - (bx) = 0, 所以zf = 1;

    如果(ax) != (bx)(ax) - (bx) != 0, 所以zf = 0;

    如果(ax) < (bx)(ax) - (bx) 将产生借位, 所以cf = 1;

    如果(ax) >= (bx)(ax) - (bx) 不必借位, 所以cf = 0;

    如果(ax) > (bx)(ax) - (bx)既不借位,结果又不为0, 所以cf = 1并且zf = 0;

    如果(ax) <= (bx)(ax) - (bx) 既可能借位,结果可能为0, 所以cf = 1或zf = 1;

    指令cmp ax, bx的逻辑含义是比较ax和bx中的值,如果执行后

    zf = 1,说明(ax)=(bx)

    zf = 0,说明(ax)!=(bx)

    cf = 1,说明(ax)<(bx)

    cf = 0,说明(ax)>=(bx)

    cf = 0并且zf = 0,说明(ax)>(bx)

    cf = 1或zf = 1,说明(ax)<=(bx)

    以上是无符号的比较逻辑

    cmp既可以对无符号进行比较,也可以对有符号进行比较,上面所说的是对无符号数进行比较时,相关标志位对比结果的记录

    有符号的比较结果

    如果因为溢出导致实际结果为负,那么逻辑上真正的结果必然为正。

    如果因为溢出导致实际结果为正,那么逻辑上真正的结果必然为负

    pushf和popf

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

    pushf和popf,为直接访问标志寄存器提供了一种方法

    标志寄存器在debug中的表示

  • 相关阅读:
    gulp图片压缩 gulp-imagemin
    $q.all() 的异步处理问题
    angular.forEach()
    js判断数据类型是否为字符串
    vue项目build后,服务器中运行程序成功,但是刷新页面以后就挂了
    移动端动态布局 设置字体大小
    js和angularjs之间的相互调用
    关于WebUploader上传文件插件的headers.token拦截问题
    vue+elementUI 时间范围选择器
    深入理解计算机系统_3e 第八章家庭作业 CS:APP3e chapter 8 homework
  • 原文地址:https://www.cnblogs.com/songyaqi/p/11888126.html
Copyright © 2011-2022 走看看