目录

  • 一、ZF标志
  • 二、PF标志
  • 三、SF标志
  • 四、CF标志
  • 五、OF标志
  • 六、adc指令
  • 七、sbb指令
  • 八、cmp指令
  • 九、检测比较结果的条件转移指令
  • 十、DF标志和串传送指令
  • 十一、pushf和popf

CPU内部的寄存器中,有一种特殊的寄存器,具有以下3种作用

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

这种特殊的寄存器在8086CPU中,被称为标志寄存器,8086CPU的标志寄存器有16位,其中存储的信息通常被称为程序状态字(PSW),我们已经使用过8086CPU的ax、bx、cx、dx、si、di等13个寄存器,本章中的标志寄存器(flag)是最后一个寄存器

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


flag的1、3、5、12、13、14、15位在8086CPU中没有使用,不具有任何含义,而其他位都具有特殊的含义

这一章中,我们学习相关标志位以及典型指令

一、ZF标志

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

比如指令

mov ax,1
sub ax,1
执行后,结果为0,ZF = 1
mov ax,2
sub ax,1
执行后,结果不为0,ZF = 0

二、PF标志

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

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

三、SF标志

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

10000001B可以看作是无符号数129,也可以看作是有符号数-127


四、CF标志

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

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

五、OF标志

如果超出了机器所能表示的范围称为溢出。

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

比如说,指令运算的结果用8位寄存器或是内存单元来存放,比如add al,3,那么对于8位的有符号数据,机器所能表示的范围就是-128 ~ 127,同理,对于16位有符号数据,机器所能表示的范围就是-32768 ~ 32767

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

这里所讲到的溢出只是对有符号数运算而言。下面看两个溢出的例子:

mov al,98
add al,99

执行后将产生溢出,因为add al,99的有符号数运算是:(al)=(al)+99 = 99 + 98 = 197,结果197超过了8位有符号的范围

因为进行的是有符号数运算,所以al中存储的是有符号数,而C5H是由符号数-59的补码,如果我们用add指令进行的是有符号数运算,则99 + 98 = -59这样子的结果是无法接受的,造成这种情况的原因实际上对应的结果是197,为一个由符号数,在8位寄存器al中存放不下。

由于在进行有符号数运算时,可能会发生溢出而造成严重的结果错误。则CPU需要对指令执行后是否产生溢出进行记录。flag的第11位是OF,溢出标志位,一般情况下,OF记录了有符号数运算的结果是否发生了溢出。如果发生了溢出,则OF = 1,如果没有CF = 0

CF是对无符号数运算有意义的标志位,而OF是对有符号数运算有意义的标志位。

比如:

mov al,98
add al,99

add指令执行后,CF = 0,OF = 1,CPU在执行add等指令的时候就包含了两种含义:无符号数和有符号数的运算。对于无符号数运算,CPU用CF位来记录是否产生了进位;对于有符号数来说,用OF来记录是否产生了进位,当然还有CF来记录有结果的符号。对于无符号运算,99+98没有进位,CF=0,对于有符号数的运算,99+98发生了溢出,OF=1


六、adc指令

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

指令格式:adc 操作对象1,操作对象2
功能:操作对象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,执行的时候相当于是计算:(ax)+1+CF = 2 + 1 + 1

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

为什么CPU要提供这样一条指令?

在执行adc指令的时候加上CF值的含义是由adc指令前面的指令所决定的,也就是说,关键在于所加上的CF值被什么指令设置的。显然,如果CF的值是被sub指令设置的,那么它的含义加上借位值,如果是被add指令设置的,它的含义就是进位值

下面的指令和add ax,bx具有相同的结果:

add al,bl
adc ah,bh

看来CPU提供adc指令的目的就是用来进行加法的第二部运算的。adc指令和add指令相配合就可以对更大的数据进行加法运算。

编程,计算1EF000H+201000H,结果存在ax(高16位)bx(低16)
因为两个数据的位数都大于16,用add指令无法进行计算。我们将计算分两步进行,先将低16位相加,然后将高16位和进位值相加。

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

adc指令执行后,可能产生进位值,所以也会对CF位进行设置。由于有这样的功能,我们就可以对任意大的数据进行加法运算

编程,计算1EF0001000H+2010001EF0H,结果存在ax(最高16位)bx(次高16位)cx(低16位)

  1. 先将低16位进行相加,完成后,CF记录本次相加的进位值
  2. 然后将次高16位和CF相加,完成后CF记录本次进位
  3. 最高16位和CF相加,完成后,CF中记录本次相加的进位值
mov ax,001EH
mov bx,0F000H
mov cx,1000H
add cx,1EF0H
adc bx,1000H
adc ax,0020H

七、sbb指令

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

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

比如指令:sub 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

八、cmp指令

cmp是比较指令,cmp的功能相当于是减法指令,只是不保存结果。cmp指令执行后,将对标志寄存器产生影响。其他相关指令通过识别这些被影响的标志寄存器来得知比较结果。

cmp 指令格式:cmp 操作对象1,操作对象2

功能:计算操作对象1 - 操作对象2,但不保存结果,仅仅根据计算结果对标志寄存器来进行设置

比如:指令cmp ax,ax,做(ax)-(ax)的运算,结果为0,但并不在ax中保存,仅影响flag的相关各位。——比如看借不借位,结果为不为0决定了CF和ZF

cmp ah,bh
如果(ah)=(bh),则(ah)-(bh) = 0,所以zf = 1
如果(ah)≠(bh),则(ah)-(bh) ≠ 0,所以zf = 0

所以可以根据cmp指令执行后的zf值,就可以判断两个数据是否相等

对于有符号数,(ah)< (bh)的情况下,(ah)-(bh)可能会引起sf = 1,即结果为负。但是结果为负不一定说明(ah)<(bh),比如(ah)-(bh) = 34 - (-96) = 82H,82H是-126的补码,所以sf = 1


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

转移指的是他可以修改IP,而条件指的是他可以根据某种条件,决定是否修改IP

比如,jcxz就是一个条件转移指令,他可以检测cx中的数值,如果(cx)=0,就修改IP,否则什么也不做。所有条件转移位移都是-128 ~ 127

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

下面是常用的根据无符号数的比较结果进行转移的条件转移指令:

指令 含义 检测的相关标志位
je 等于则转移 zf = 1
jne 不等于则转移 zf = 0
jb 低于则转移 cf = 1
jnb 不低于则转移 cf = 0
ja 高于则转移 cf = 0且zf = 0
jna 不高于则转移 cf = 1或zf = 1

e表示equal
ne表示not equal
b表示below
nb表示not below
a表示above
na表示not above

这些都是cmp指令进行无符号数比较的时候,记录比较结果的标志位,比如je,检测zf位,当zf = 1的时候,进行转移,如果在je前面使用了cmp指令,那么je对zf的检测实际上就是间接的堆cmp比较结果。

编程实现如下功能:如果(ah)=(bh)则(ah)=(ah)+(ah),否则(ah)=(ah)+(bh)

cmp ah,bh
je s
add ah,bj;否则的情况
jmp short ok
s:add ah,ah
ok:...

十、DF标志和串传送指令

flag的第十位是DF,方向标志位。在串处理指令中,控制每次操作后si和di的增减

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

下面看一个串传送指令:
格式:movsb
功能:执行movsb相当于进行下面几步操作:

  1. ((es)*16+(di)) = ((ds)*16+(si))
  2. 如果df = 0,则(si)=(si)+1,(di)=(di)+1;如果df = 1,则相应减1

汇编语言描述movsb功能如下:
``mov es:[di],byte ptr ds:[si] ;可以看作底层是这样子写

如果df = 0
inc si
inc di

如果df = 1
dec si
dec di

可以看出,movsb的功能是将ds:si指向的内存单元中的字节送入es:di,然后根据df的值,将si和di+1或是-1

当然也可以传送一个字:
格式:mov sw
mov es:[di],word ptr ds:[si];可以看作底层是这样子写

如果df = 0
add si,2
add di,2

如果df = 1
sub si,2
sub di,2

movsb和movsw进行的是串传送操作的一个步骤,一般来说,movsb和movsw都是和rep配合使用,格式如下:
rep movsb
用汇编语法来描述rep movsb的功能就是:
s: movsb
loop s

可以看出,rep的作用是根据cx,重复执行后面的串传送指令。由于每执行依次movsb指令si和di都会递增或是递减指向后一个单元或是前一个单元。则rep movsb就可以循环实现(cx)个字符的传送

同理,也可以使用这样子的指令:rep movsw

相当于是:
s: movsw
loop s

由于flag的df位决定着串传送指令执行后,si和di改变的方向,所以CPU应该提供相应的指令来对df位进行设置,从而使程序员能够决定传送的方向。

8086CPU提供下面两条指令对df位进行设置:
cld指令:将标志寄存器的df置为0
std指令:将标志寄存器的df置为1

看下面两个程序:

  1. 用串传送指令,将data段中的第一个字符串复制到他后面的空间中
data segmentdb 'welcome to masm'db 16 dup(0)
data ends

传送的原始位置:ds:si
传送的目的位置:es:di
传送的长度:cx
传送的方向:df

mov ax,data
mov ds,ax
mov si,0 ;ds:si指向data:0
mov es,ax
mov di,16
mov cx,16
cld
rep movsb

十一、pushf和popf

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

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

[汇编语言]标志寄存器相关推荐

  1. 汇编语言--标志寄存器

    标志寄存器      CPU内部的寄存器中,有一种特殊的寄存器(对于不同的处理机,个数和结构都可能不同)具有以下3种作用. 用来存储相关指令的某些执行结果: 用来为CPU执行相关指令提供行为依据: 用 ...

  2. Win-MASM64汇编语言-标志寄存器(EFLAGS/PSW/PUSHF/POPF)

    CPU内部需要一种特殊的寄存器来完成下面三个功能 1.用来存储相关指令的执行结果是否满足某些特性 2.为cpu执行相关指令提供行为依据 3.用来控制cpu的相关工作方式 能完成上面三个功能的寄存器被成 ...

  3. 汇编语言随笔(3)-条件转移指令和标志寄存器

    标志寄存器 标志寄存器通常具有以下三种作用:       1,用来存储相关指令的某些执行效果       2,用来为CPU执行相关指令提供行为依据       3,用来控制CPU的相关工作方式     ...

  4. 《汇编语言(第三版)》pushf 和 popf 指令,以及标志寄存器在 Debug 中的表示

    pushf 和 popf pushf 的功能是将标志寄存器的值压栈,而 popf 是从栈中探出数据,输入标志寄存器. pushf 和 popf,为直接访问寄存器提供了方法. 格式 pushf popf ...

  5. 《汇编语言(第三版)》标志寄存器

    标志寄存器 8086CPU中的flag寄存器包括: CF.PF.ZF.SF.OF.DF. 传送指令不影响标志寄存器 ZF标志寄存器 zf标志寄存器位于flag中的第6为,表示零标志位.(至于flag是 ...

  6. 汇编语言之标志寄存器

     1.标志寄存器 CPU内部的寄存器中,有一种特殊的寄存器(对于不同的处理机,个数和结构都可能不同)具有以下3种作 用: 1. 用来存储相关指令的某些执行结果. 2. 用来为CPU执行相关指令提供 ...

  7. 王爽 汇编语言第三版 第11章 标志寄存器

    条件码: ① OF(Overflow Flag)溢出标志,溢出时为1,否则置0.标明一个溢出了的计算,如:结构和目标不匹配. ② SF(Sign Flag)符号标志,结果为负时置1,否则置0. ③ Z ...

  8. 汇编语言笔记(三): 标志寄存器

    章节目录 简介 ZF 标志寄存器 PF 标志寄存器 SF 标志寄存器 CF 标志寄存器 OF 标志寄存器 几条相关指令 DF 标志寄存器 PUSHF and POPF 标志寄存器 作者能力有限, 如果 ...

  9. 【汇编语言】标志寄存器PSW

    简介 8086CPU设置了一个16位标志寄存器PSW(也叫FR). 其中规定了9个标志位,用来存放运算结果特征和控制CPU操作. 反映指令对数据作用之后,结果的状态(不是结果本身).这些状态将控制后续 ...

最新文章

  1. webpack-dev-server 和webapck --watch的区别
  2. 什么是java序列化,如何实现java序列化?
  3. 在SharePoint环境中更换密码
  4. 【CodeForces - 144C】Anagram Search(尺取,滑窗问题,处理字符串计数)
  5. oracle表空间如何压缩,Oracle里表空间的压缩
  6. 线程等待通知 linux,Java 线程协作 wait(等待)与 notiy(通知)
  7. ASCII表 基本记忆 -- C
  8. [osg][原创]osg多屏幕显示,会出现透明需要设置的问题
  9. 基于遥感图像的船舶目标识别技术
  10. android handler的机制和原理_Android基础(7)—异步消息处理机制 Handler
  11. APM_ArduCopter源码解析学习(二)——电机库学习
  12. 操作系统基础知识复习总结
  13. 关于Pycharm进行pytorch分布式训练代码
  14. Java中RuntimeException和Exception区别
  15. tensorboard--曲线图颜色深浅两条线
  16. 【游戏开发实战】Unity循环复用列表,支持不规则尺寸(对象池 | UGUI | ScrollRect | Demo源码)
  17. 555-大数据查重-位图算法
  18. 网页防篡改技术发展趋势
  19. 在疫情期间微分销商城如何运营
  20. Voltus任命全球投资者关系负责人

热门文章

  1. python招聘现状-python招聘现状
  2. 什么是云平台,云平台的分类和优势有哪些?
  3. Python:使用PyAV提取视频关键帧
  4. FHQ_TREAP学习笔记
  5. HorizontalScrollView 滑动处理
  6. 输出100内所含5或5的倍数的值(Python)
  7. 华为鸿蒙战略发布会视频,华为公布鸿蒙手机操作系统开机画面视频
  8. 关于COM类工厂80070005和8000401a错误分析及解决办法(DCOM)
  9. 防复制防破解小区门禁梯控升级非联网CPU卡脱机写卡门禁梯控一卡通系统92HID623CPU V5.00操作说明之用户卡加密发卡设置说明
  10. html网站底部导航栏怎么做,如何设计一个页面的底部导航?