• 汇编语言-标志寄存器


    汇编语言-标志寄存器

    CPU内部的寄存器中,有一个特殊的寄存器,叫标志寄存器,它具有以下三种作用:

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

    flag和其他寄存器不一样,其他寄存器是用来存放数据的,都是整个寄存器具有一个含义。
    而flag寄存器是按位起作用的,也就是说,它的每一位都有专门的含义,记录特定的信息。

    标记寄存器内部结构及其功能简介


    ZF标志

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

    代码示范

    mov ax,1
    
    sub ax,1
    
    执行后,结果为0,则ZF=1,表示“结果是0”。

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


    PF标志

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

    代码示范

    mov al,1
    
    add al,10
    
    执行后,结果为00001011B,其中有3(奇数)个1,则PF=0


    SF标志

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

    代码示范

    mov al,10000001B
    
    add al,1
    
    执行后,结果为10000010B,符号位为1,则SF=1


    CF标志

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

    代码示范

    mov al,98H
    add al,al          ;执行后,(al) = 30H, CF=1, CF记录了从最高有效位向更高位的进位值
    add al,al     ;执行后,(al) = 60H, CF=0, CF记录了从最高有效位向更高位的进位值
    
    
    mov al,97H
    sub al,98H             ;执行后,(al) = FFH, CF=1, CF记录了向更高位的借位值
    sub al,al                 ;执行后,(al)=0,CF=0,CF记录了向更高位的借位值


    OF标志

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

    一定要注意CF和OF的区别:CF是对无符号数运算有意义的标志位,而OF是对有符号数运算有意义的标志位。

    mov al,98
    add al,99
    add指令执行后:CF=0,OF=1


    adc指令

    adc 操作对象1,操作对象2

    功能:

    操作对象1=操作对象1+操作对象2+CF

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

    代码示范

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


    sbb指令

    使用方法和adc指令相似


    cmp指令

    cmp是比较指令,cmp的功能相当于减法指令,只是不保存结果。

    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


    检测比较结果的条件转移指令

    “转移”指的是它能够修改IP,而“条件”指的是它可以根据某种条件,决定是否修改IP。

    比如:jcxz就是一个条件转移指令,它可以检测cx中的数值,如果(cx)=0,就修改IP,否则什么也不做。

    所有条件转移指令的转移位移都是[-128~127]。

    除了jcxz之外,CPU还提供了其他条件转移指令,大多数条件转移指令都检测标志寄存器的相关标志位,根据检测的结果来决定是否修改IP。

    它们检测的是哪些标志位呢?就是被cmp指令影响的那些,表示比较结果的标志位。这些条件转移指令通常都和cmp相配合使用,就好像call和ret指令通常相配合使用一样。

    因为cmp指令可以同时进行两种比较,无符号数比较和有符号数比较,所以根据cmp指令的比较结果进行转移的指令也分为两种,即:

    • 根据无符号数的比较结果进行转移的条件转移指令,它们检测ZF、CF的值;
    • 和根据有符号数的比较结果进行了转移的条件转移指令,它们检测SF、OF和ZF的值。

    指令介绍:

    这里写图片描述

    代码示范

    如果(ah)=(bh)则(ah)=(ah)+(ah),否则(ah)=(ah)+(bh)。

    cmp ah,bh
    
    je s
    
        add ah,bh
        jmp short ok
    
    s:add ah,ah
    
    ok:

    上面的程序执行时,如果(ah)=(bh),则cmp ah,bh 使ZF=1,而je检测ZF是否为1,如果为1,将转移到标号s处执行指令 add ah,ah。这也可以说,cmp比较ah、bh后所得到的相等的结果使得je指令进行转移。从而很好地体现了je指令的逻辑含义,相等则转移。

    虽然je的逻辑含义是“相等则转移”,但它实际进行的操作是,ZF=1时则转移。

    “相等则转移”这种逻辑含义,是通过和cmp指令配合使用来体现的,因为cmp指令为“ZF=1”赋予了“两数相等”的含义。

    至于究竟在je之前使不使用cmp指令,在于我们在安排je检测的是ZF位置,不管je前面是什么指令,只要CPU执行je指令时,ZF=1,那么就会发生转移。

    实例介绍

    程序功能:将包含任意字符,以0结尾的字符串中的小写字母转变成大写字母

    assume cs:code
    
    data segment
        db 'sfsd;++dfasd"fdsafsd_fdfdfdIIIIss',0
    data ends
    
    code segment
    
    start:  mov ax,data
        mov ds,ax
        mov si,0
        call letterc
    
        mov ax,4c00H
        int 21
    
    letterc:
        push ax
        push ds
        push si
    
    s:  
        mov al,ds:[si]
        mov ah,'a'
        cmp al,ah
        jb next
        mov ah,'z'
        cmp al,ah
        ja next
    
    change:     
        and al,11011111B
        mov ds:[si],al
    
    next:
        inc si
    loop s
    
        pop si
        pop ds
        pop ax
    
    code ends
    end start

    效果图:


    DF标志和串传送指令

    DF标记

    flag的第10位是DF,Direction Flag,方向标志位。

    在串处理指令中,控制每操作后si,di的增减。

    DF=0,每次操作后si,di递增;DF=1,每次操作后si,di递减。

    DF相关指令

    8086CPU提供下面两条指令对DF位进行设置:

    cld指令:将标志寄存器的DF位置0std指令:将标志寄存器的DF位置1


    串传送指令

    格式:movsb

    功能介绍

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

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

    用汇编语法描述movsb的功能如下:

    mov es:[di],byte ptr ds:[si]           ;8086CPU并不支持这样的指令,这里只是个描述。
    
    如果DF=0inc si
        inc di
    
    如果DF=1dec si
        dec di

    rep指令

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

    movsb和movsw都和rep配合使用,格式如下:

    mov cx,100
    rep movsb

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

    mov cx,100
    s:movsb
    loop s


    pushf和popf

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

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

  • 相关阅读:
    【尺取法】
    [USACO12MAR]花盆Flowerpot [单调队列]
    数据库笔记
    NYOJ 91 阶乘之和(贪心)
    NYOJ 71 独木舟上的旅行(贪心)
    水池数目(DFS)
    poj 1164城堡问题(DFS)
    NYOJ 12 喷水装置(二)( 贪心)
    NYOJ 6(贪心)
    NYOJ 45( 分治,大数)
  • 原文地址:https://www.cnblogs.com/AbeDay/p/5026855.html
Copyright © 2020-2023  润新知