惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - Franky
N
Netflix TechBlog - Medium
Google Online Security Blog
Google Online Security Blog
月光博客
月光博客
量子位
酷 壳 – CoolShell
酷 壳 – CoolShell
V
V2EX
腾讯CDC
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - 聂微东
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
M
MIT News - Artificial intelligence
Vercel News
Vercel News
The GitHub Blog
The GitHub Blog
Hugging Face - Blog
Hugging Face - Blog
博客园 - 【当耐特】
Apple Machine Learning Research
Apple Machine Learning Research
aimingoo的专栏
aimingoo的专栏
博客园 - 三生石上(FineUI控件)
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
MongoDB | Blog
MongoDB | Blog
H
Help Net Security
The Cloudflare Blog
Blog — PlanetScale
Blog — PlanetScale
F
Full Disclosure
G
Google Developers Blog
罗磊的独立博客
Jina AI
Jina AI
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Y
Y Combinator Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
J
Java Code Geeks
A
About on SuperTechFans
IT之家
IT之家
大猫的无限游戏
大猫的无限游戏
S
SegmentFault 最新的问题
有赞技术团队
有赞技术团队
GbyAI
GbyAI
雷峰网
雷峰网
T
The Blog of Author Tim Ferriss
The Register - Security
The Register - Security
U
Unit 42
D
Docker
Martin Fowler
Martin Fowler
L
LINUX DO - 热门话题
NISL@THU
NISL@THU
阮一峰的网络日志
阮一峰的网络日志
C
Cybersecurity and Infrastructure Security Agency CISA
博客园_首页
Google DeepMind News
Google DeepMind News

faryou的博客

5月月考 - faryou的博客 - 日记 faryou的博客-五一回老家 【汇编 - 功能】中断安装中断实现 【汇编&硬件】时钟中断的具体实现 faryou的博客-这些年,我不再看《熊出没》 【汇编&硬件】关机中断的具体实现 【汇编&硬件】网络连接相关中断的具体实现 faryou的博客-年初小记 【汇编&硬件】鼠标控制中断的具体实现 【汇编&硬件】声音输出中断的具体实现 【汇编&硬件】屏幕输出中断的具体实现 【汇编&硬件】磁盘读取中断的具体实现 【汇编&硬件】键盘读取中断的具体实现 【汇编】汇编环境的搭建及Debug的使用教程 【汇编】漫谈:学习汇编后的一些思考 faryou的博客-关于本站即日起实行“一站三体”运营制度 【汇编基础教程】完结篇 写在最后:前言 【汇编基础教程】使用BIOS的中断实现键盘输入及磁盘I/O 【汇编基础教程】中断 【汇编基础教程】端口 【汇编基础教程】再谈栈 【汇编基础教程】段 【汇编基础教程】来存一些数据! 【汇编基础教程】寄存器和内存&一些基本命令的说明 【汇编基础教程】来写个“函数” 【汇编基础教程】更灵活的定位内存 【汇编基础教程】理解一下[bx]和loop指令 【汇编基础教程】跳一跳! faryou的博客-我的竞赛经历&对人生的一些思考 faryou的博客-关于现在中小学计算机课的一些想法及思考 faryou的博客-2025年度总结 faryou的博客-临平山下十五年 faryou的博客-Windows 10即将停止支持,谈谈自己从小到大用电脑的感受 faryou的博客-谈谈一名10后的怀旧情怀 【汇编基础教程】8086CPU工作原理 【C语言】指针的理解与应用 【算法教程】【C/C++】DP(动态规划):区间DP——程序设计思路与代码实现 【算法教程】【C/C++】BFS(广度优先搜索)——程序设计思路与代码实现 【算法教程】【C/C++】DFS(深度优先搜索)——程序设计思路与代码实现 【算法教程】【C/C++】单源最短路径——程序设计思路与代码实现 【算法教程】【C/C++】最小生成树——程序设计思路与代码实现 【算法教程】【C/C++】并查集——程序设计思路与代码实现 【算法教程】【C/C++】DP(动态规划):背包DP——程序设计思路与代码实现 【算法教程】【C/C++】DP(动态规划):简单动规问题——程序设计思路与代码实现 【算法教程】【C/C++】递推——程序设计思路与代码实现 【算法教程】【C/C++】三分算法——程序设计思路与代码实现 【算法教程】【C/C++】二分答案——程序设计思路与代码实现 【算法教程】【C/C++】二分查找——程序设计思路与代码实现 【算法教程】【C/C++】贪心算法——程序设计思路与代码实现 【算法教程】【C/C++】基础数学:快排——程序设计思路与代码实现 【算法教程】【C/C++】基础数学:快速幂——程序设计思路与代码实现 【算法教程】【C/C++】基础数学:进制转换——程序设计思路与代码实现 一文弄懂C++中的自定义函数 faryou的博客-2024年度总结
【汇编基础教程】标志寄存器
作者: faryou · 2026-01-30 · via faryou的博客

前言

在8086CPU中,有一个特殊的寄存器,用来存放各种指令产生的临时信息,它被称为flag,即标志寄存器。本文将介绍该寄存器的使用,在编程时应灵活使用其特性。

标志寄存器简介

标志寄存器可以视为几个单二进制位的寄存器所拼凑出来的一个寄存器(几个各具自己含义的单二进制位的寄存器挤在同一个寄存器里面),存放一些指令执行时产生的附加信息(如加减法时的进位、借位,溢出等)。在标志寄存器中,每个二进制位代表一个信息。下面将详细介绍各标志寄存器的用途~

标志寄存器组成

标志寄存器由以下各位组成:
  位数  15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0
  表示              OF DF IF TF SF ZF    AF    PF    CF
其中空的位没有实际意义,有意义的位将进行介绍——

标志寄存器使用

DF标志(第10位,方向标志位)与串传送指令

DF标志控制串传送指令每次操作后si、di的增减。若DF值为0,则每次操作后si、di递增;若DF值为1,则每次操作后si、di递减。
串传送指令用于在内存中移动一批数据。其中movsb针对一个字节,movsw针对一个字。movsb的功能如下:

(1)将ds:si指向的内存单元字节送入es:di处。
(2)若DF值为0,则si、di各自增1;
    若DF值为1,则si、di各自减1。

同理,movsw的功能如下:

(1)将ds:si指向的内存单元字送入es:di处。
(2)若DF值为0,则si、di各自增2;
    若DF值为1,则si、di各自减2。

串传送指令一般和rep配合使用,如:

rep movsb

其等价于:

s:movsb
  loop s

易知rep的作用:可以实现(cx)个字节/字的传送。
由此,不难想到,CPU应提供直接更改DF值的方式。事实确实如此。在8086CPU中,我们可以通过cld/std指令将DF的值设置为0/1,格式:

cld/std

ZF标志(第6位,零标志位)

ZF标志用于记录相关指令执行后,其结果是否为0。若结果为0,则ZF值为1;反之则ZF值为0。其中,add、sub、mul、div、inc、or、and等运算指令会影响ZF的值。例如,执行如下指令后,ZF值为1:

mov ax,1
sub ax,1

PF标志(第2位,奇偶标志位)

PF标志用于记录一些指令执行后,其结果的所有单字节位中1的个数是否为偶数。若为偶数,则PF值为1;反之则PF值为0。例如,执行如下指令后,PF值为0:

mov al,1
or al,1

SF标志(第7位,符号标志位)

SF标志记录一些指令执行后,其结果是否为负。若结果为负,则SF值为1;否则SF值为0。需要注意的是,计算机中存放的数字有无符号数和有符号数两种,而一个字节单元存放的数有无符号由编程者意识决定。当你认为运算对象是有符号数时,8086CPU会将运算结果视为补码,并将其转为原码后判断其符号位的正负来更新SF位的值;当你认为运算对象是无符号数时,CPU也会以相同方式更新SF位,但此时符号对你没有意义,所以请无视SF位。例如,执行如下指令后,SF值为0(运算结果换成原码后为0,即非负数):

mov al,10000001b
add al,01111111b

CF标志(第0位,进退位标志位)

CF标志记录add、sub执行后最高位是否产生进、退位。若产生了进、退位,则CF值为1;反之则CF值为0。需要注意的是,inc和loop指令不影响CF位。
abc、sbb指令
abc、sbb指令是带借位加、减法指令。相当于在操作目标上再加、减一个CF的值,例如:

add al,bl
abc ah,bh

以上指令等效于:

add ax,bx

由此可见,我们可以通过abc和sbb指令进行大数据相加。例如,以下代码能计算1EF0001000H+2010001EFH的值,其中高、中、低16位分别存放在ax、bx、cx寄存器中:

mov ax,001EH
mov bx,0F000H
mov cx,1000H
add cx,1EF0H
abc bx,1000H
abc ax,0020H

OF标志(第11位,溢出标志位)

我们在进行有符号数运算时,可能会发生溢出,这会导致运算结果不正确。例如,我们要将两个8位二进制数(范围-128~127)98和99相加,正确结果是197。但是,由于机器无法存下,发生了溢出,我们得到了-59,显然,这与我们的希望不符。
OF标志位就是用于记录溢出的位。如果发生溢出,OF值为1;反之OF值为0。上面的98+99运算后,OF值为1。但需要注意OF和CF的区别。CF针对无符号数,而OF针对有符号数。

cmp指令和检测比较结果的条件跳转指令

cmp指令为比较指令,格式:
cmp 操作对象1,操作对象2
当执行cmp指令时,CPU会对两个操作对象作减法,但不保存在操作对象中,只影响标志寄存器的值。例如,执行如下指令后,ZF值为0,PF值为1,SF值为0,CF值为0,OF值为0:

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

则执行cmp指令后,我们通过标志寄存器的值即可判断两个操作对象的大小。由逻辑推理,我们可以得到:

当ZF值为1时,(ax)=(bx)
当CF值为1时,(ax)<(bx)
当CF值为0且ZF值为0时,(ax)>(bx)

对于有符号数,由于其靠补码表示,故情况较为复杂:

当SF值与OF值不同时,(ax)<(bx)
当SF值与OF值相同时,(ax)≥(bx),然后根据ZF的值判断是否相等

通过上面的讨论,我们知道了不同比较结果下cmp指令的实际意义,下面介绍常用的使用cmp比较结果的方法——检测比较结果的条件转移指令。对于无符号数,其条件转移指令如下:

je/jz:等于(ZF值为1)则转移
jne/jnz:不等于(ZF值为0)则转移
ja/jnbe:高于(CF、ZF值均为0)则转移
jna/jbe:不高于(CF、ZF中至少一个值为1)则转移
jb/jnba:低于(CF值为1)则转移
jnb/jae:不低于(CF值为0)则转移

对于有符号数,其条件转移指令如下:

je/jz:等于(ZF值为1)则转移
jne/jnz:不等于(ZF值为0)则转移
jg/jnle:大于(SF、OF值相等且ZF值为1)则转移
jng/jle:不大于(SF、OF值不等或ZF值为0)则转移
jl/jnge:小于(SF、OF值不等)则转移
jnl/jge:不小于(SF、OF值相等)则转移

如果只想要用其中一个标志位,则可以使用下面针对某一个位的指令:

jc/jo/jp/js:CF/OF/PF/SF值为1则转移
jnc/jno/jnp/jns:CF/OF/PF/SF值为0则转移

以ja为例,以上全部转移指令的格式:

ja 标号

将ja替换为其他指令也可。注意,以上条件转移指令均为短转移。

AF标志(第四位,辅助进退位标志位)

AF标志位用于BCD码运算相关操作。BCD码是一种用一组四个二进制位表示十进制数的编码。若两数相加,其中低四位的最高位有进位,则AF值为1,反之AF值为0。

直接获得标志寄存器中的数据

8086CPU支持直接访问标志寄存器的数据。pushf能够将标志寄存器压栈,popf刚能够从栈中弹出数据到标志寄存器中,格式:

pushf/popf

同时,还有一个lahf指令,能够将标志寄存器的低8位送入ah寄存器。格式:

lahf

在得到标志寄存器中的数据后,我们即可通过位运算指令,建立值-指令映射关系,同样可以实现类似条件转移指令的功能(高级语言中if语句的底层逻辑就是映射)。