• 第11章标志寄存器 其一


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

    我们已经使用过8086cpu的ax、bx、cx、dx、si、di、bp、sp、ip、cs、ss、ds、es等13个寄存器了。

    本章中的标志寄存器(以下简称flag)是我们要学习的最后一个寄存器。

    flag和其他寄存器不一样,其他寄存器是用来存放数据的,都是整个寄存器具有一个含义。

    而flag寄存器是按位起作用的,也就是说,他的每一位都有专门的含义,记录特定的信息。

    在这一章中,我们学习标志寄存器中的cf、pf、zf、sf、of、df标志位,和一些与其相关的典型指令。

    11.1zf标志位

    flag 的第6位是zf,零标志位。它记录相关指令执行后,

    结果为0,zf=1

    结果不为0,zf=0

    比如:

    mov  ax,1

    sub  ax,1

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

    mov  ax,2

    sub  ax,1

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

    对于zf的值,我们可以这样来看,zf标记相关指令的计算结果是否为0,如果为0,则在zf要记录下  是0  这样的肯定信息。

    注意:

    在8086cpu的指令集中,有的指令的执行是影响标志寄存器的,比如:

    add、sub、mul、div、inc、or、and等,他们大都是运算指令(进行逻辑或算数运算)

    有的指令的执行对标志寄存器没有影响,比如:mov,push、pop等,他们大都是传送指令。

    11.2  pf标志

    flag的第二位是pf,奇偶标志位。他记录指令执行后,结果的所有二进制位中1的个数;

    为偶数,pf=1

    为奇数,pf=0.

    示例:

    指令:

    mov  al,1

    add al,10

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

    指令:

    mov al,1

    or al,10

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

    11.3  sf标志位

    flag的第7位是sf,符号标志位。

    它记录指令执行后,

    结果为负,sf=1.

    结果为正,sf=0.

    示例:

    mov  al,10000001b

    add al,1

    结果:al=10000010b

    我们可以将add指令进行的运算当作无符号数的运算,那么add指令相当于计算129+1,结果为130(10000010b)

    也可以将add指令进行的运算当作有符号数的运算,那么add指令相当于计算-127+1,结果为-126(10000010b)

    不管我们如何看待,cpu在执行add指令的时候,就已经包含了两种含义,也将得到用同一种信息来记录的两种结果

    关键在于我们的程序需要哪一种结果

    sf标志,就是cpu对有符号数运算结果的一种记录,它记录数据的正负。

    在我们将数据当作有符号数来运算的时候,可以通过它来得知结果的正负。

    如果我们将数据当作无符号数来运算,sf的值则没有意义,虽然相关的指令影响了它的值。

    11.4   CF标志

    flag的第0位是cf,进位标志位。

    一般情况下,在进行无符号数运算的时候,它记录了运算结果的最高有效位向更高位的进位值,或从更高位的借位值

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

     我们知道,当两个数据相加的时候,有可能产生从最高有效位向更高位的进位。

    比如,两个8位数据,98H+98H,将产生进位。

    由于这个进位值在8位数中无法保存,cpu就把它记录在一个特殊的寄存器的某一位上。

    8086cpu就用flag的cf位来记录这个进位值。

    而当两个数据做减法的时候,有可能向更高位借位。

    此时也是用cf来记录这个借位值。

    11.5  OF标志

    在进行有符号数运算的时候,如结果超过了机器所能表示的范围称为溢出。

    什么是机器所能表示的范围呢?

    比如说,指令运算的结果用8位寄存器或内存单元来存放。

    比如:add  al, 3 那么对于8位的有符号数据,机器所能表示的范围就是-128~127.

    t同理,对于16位有符号数,机器所能表示的范围是-32768~32767

    如果运算结果超出了机器所能表达的范围,将产生溢出。

    注意,这里所讲的溢出,知识对有符号数运算而言。

     如果在进行有符号数运算时发生溢出,那么运算的结果将不正确。

    flag的第11位是OF,溢出标志位,用来记录指令执行后是否产生溢出。

    一般情况下,of记录了有符号数运算的结果是否发生了溢出。

    如果发生溢出,of=1

    如果没有,of=0.

    要注意cf和of的区别:

    cf是对无符号数运算有意义的标志位

    而of是对有符号数运算有意义的标志位。

    比如:

    mov  al,98

    add   al,99

    add指令执行后,cf=0,of=1

    前面我们讲过,cpu在执行add等指令的时候,就包含了两种含义:无符号数运算和有符号数运算。

    对于无符号数运算,cpu用cf位来记录是否产生了进位

    对于有符号数运算,cpu用of位来记录是否产生了溢出。

    当然,还要用sf位来记录结果的符号。

    对于无符号数运算,98+99没有进位,cf=0

    对于有符号数运算,98+99发生溢出,of=1.

    我们可以看出,cf和of所表示的进位和溢出,是分别对无符号数和有符号数运算而言的,他们之间没有任何关系。

    11.6  adc指令

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

    格式:adc  操作对象1,操作对象2

    功能:

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

    比如:

    adc  ax,bx实现的功能是:

    ax=ax+bx+cf

     

    如果cf的值是被sub指令设置的,那么它的含义就是借位值;如果是被add指令设置的,那么它的含义就是进位值。

     

     看来cpu提供adc指令的目的,就是来进行加法的第二步运算的。

    adc指令和add指令相配合就可以对更大的数据进行加法运算。

    编程计算1EF000H+201000H,结果放在ax(高16位)和bx(低16位)中。

    分析:

    因为两个数据的位数都大于16,用add指令无法进行滚计算。我们将计算分两步进行,先将低16位相加,然后将高16位和进位值相加。

     adc指令执行后,也可能产生进位值,所以也会对cf位进行设置。

     

     分析:

    计算分3步进行:

    1)先将低16位相加,完成后,cf中记录本次相加的进位值。

    2)再将次高16位和cf(来自低16位的进位值)相加,完成后,cf中记录本次相加的进位值。

    3)最后高16位和cf(来自次高16位的进位值)相加,完成后,cf中记录本次相加的进位值。

     

     ds:si指向存储第一个数的内存空间,因数据为128位,所以需要8个字单元,由低地址单元到高地址单元依次存放128位数据由低到高的各个字。运算结果存储在第一个数的存储空间中。

    ds:di指向存储第二个数的内存空间。

    ;编写一个子程序,对两个128位数据进行相加。
    
    ;名称:add128
    ;功能:两个128位数据进行相加
    ;参数:
    ;   ds:si指向存储第一个数的内存空间,因数据为128位,所以需要8个字单元,由低地址单元到高地址单元依次存
    ;   放128位数据由低到高的各个字。运算结果存储在第一个数的存储空间中。 
    
    ;   ds:di指向存储第二个数的内存空间
    
    add128: push ax
            push cx
            push si
            push di
    
            sub ax,ax    ;将CF设置为0
          s:mov ax,[si]
            adc ax,[di]
            mov [si],ax
            inc si
            inc si
            inc di
            inc di
            loop s
    
            pop di
            pop si
            pop cx
            pop ax
            ret  

    inc和loop指令不影响cf位,上面的程序中,不能将4个inc指令,换成

    add si,2

    add si,2

    因为那样会影响cf位。

    11.7sbb指令

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

    格式:sbb操作对象1,操作对象2

    功能:

    操作对象1=操作对象1-操作对象2-cf

    比如:sbb  ax,bx

    实现功能:ax=ax-bx-cf

    sbb指令执行后,将对cf进行设置。

    利用sbb指令可以对任意大的数据进行减法运算。

    比如,计算003e1000H-00202000H,结果放在ax,bx中,程序如下:

    mov bx,1000H

    mov ax,003eH

    sub bx,2000H

    sbb ax,0020H

    11.8 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

     

  • 相关阅读:
    OC-KVO简介
    注册审核
    应用权限
    关于函数执行的一点知识
    设置权限
    文件操作实例:文件管理器(网页版)
    文件操作
    正则表达式
    全局变量和递归
    案例:简单留言板
  • 原文地址:https://www.cnblogs.com/fate-/p/12955853.html
Copyright © 2020-2023  润新知