我是如何学习Java的~标志寄存器及其应用
在8086CPU内部的寄存器中,还存在着一种特殊的寄存器,一些指令的执行会触发该寄存器中特定位的值的改变,以用来记录指令执行的一些结果情况。这个寄存器被称为标志寄存器。
标志寄存器也是16位,但不是每一位都有特定的含义的,真正有意义的只有9位,如下:
15 | 14 | 13 | 12 | 11 | 10 | 8 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
OF | DF | IF | TF | SF | ZF | AF | PF | CF |
每一个标志位,我们可以在 DOSBOX 中通过 debug 查看:
上图中的标志位分别表示如下:
标志 | 值为1 | 值为0 |
---|---|---|
OF | OV(OVERFLOW) | NV(NOT OVERFLOW) |
DF | DN(DOWN) | UP |
IF | EI(ENABLE INTERRUPT) | DI(DIABLE INTERRUPT) |
SF | NG(NEGATIVE SIGN) | PL (PLUS SIGN) |
ZF | ZR(ZERO) | NZ(NOT ZERO) |
AF | AC( AUXILIARY CARRY) | NA(NOT AUXILIARYCARRY) |
PF | PE(PARITY EVEN) | PO(PARITY ODD) |
CF | CY(CARRY) | NC(NOT CARRY) |
下面介绍部分标志位,大家可以在dosbox中根据上述的值来进行验证。
ZF 标志
标志寄存器的第 6 位是 ZF,零标志位。该标志位记录了相关指令的执行结果是不是为 0,若结果为 0,则 ZF=1,否则,ZF=0。
如:
mov ax, 1
sub ax, ax
指令执行后,结果为 0 ,则 ZF=1。
mov ax, 2
sub ax, 1
指令执行后,结果不为 0 , 则 ZF=0。
有些指令的执行,即使结果为 0 ,也不会影响 ZF 标志位的:
mov ax, 0
像 add、sub、mul、div、inc、or、and 等运算指令都会影响标志寄存器,而有些指令则对标志寄存器没有影响,如mov、push、pop等传送指令。
PF 标志
标志寄存器的第 2 位是 PF,奇偶标志位,该标志位记录了相关指令执行后,其结果中的所有 bit 位中的 1 的个数是否为偶数。若结果是偶数,则 PF=1,否则,PF=0。
mov al, 1
and al, 0
指令执行后,结果为00000000B,有 0 个 1,为偶数,则 PF = 1。
mov al, 1
or al, 1
指令执行后,结果为00000001B,有 1 个 1,为奇数,则 PF=0。
SF 标志
标志寄存器的第 7 位是SF,符号标志位,该标志位记录了相关指令执行后,结果是否为负。如果结果为负,则 SF=1,否则,SF=0。
对于计算机中的数值,二进制来说,即可以当成有符号数,最高位代表正负,也可以当成无符号数来看待。所以,计算机在执行add等指令时,也就相当于具有了两种含义,关键在于我们需要哪一种结果。
SF 标志,就是CPU对有符号数运算结果的一种记录,在我们进行有符号数运算时,可以通过该标志位来得知结果的正负。同时,若我们当成无符号数运算时,虽然结果同样会改变 SF 的值,但该值对于无符号来说是没有意义的。
如:
mov al, 10000001B
add al, 1
指令执行后,结果为 10000010B,SF=1,表示:如果指令进行的是有符号运算,则结果为负。
CF 标志
标志寄存器中的第 0 位是 CF,进位标志位。该标志位是针对的无符号数运算,其记录了运算结果的最高有效位向更高位的进位值,或从更高位的借位值。
如:
mov al, 98H
add al, al
该指令执行后,al=30H,CF=1,该结果向更高位进位1,所以,CF 记录了从最高有效位到更高位的进位值。
mov al, 30h
add al, al
指令执行后,al=60H,CF=0,该结果向更高位进位0,所以,CF 记录了从最高有效位到更高位的进位值。
mov al, 00000010B
mov bl, 00000001B
sub bl, al
指令执行后,bl=11111111B,CF=1,该结果向更高位借位1,所以,CF记录了从最高有效位到更高位的借位值。
通过CF记录的进位或借位值,我们可以结合指令 adc 和 sbb 来计算更多位数的加减法:
如:
计算1FFFFH + 1的值,BX 存放高位,AX 存放低位:
mov ax, 0FFFFH
mov bx, 0001H
add ax, 1 ;inc不会影响CF的值,add结果会产生进位值1
adc bx, 0 ;adc表示 运算结果 + CF的值
结果为:BX=2,AX=0。即结果为20000H。
如:
计算10000H - 1的值,BX 存放高位,AX 存放低位:
mov ax, 0
mov bx, 1
sub ax, 1
sbb bx, 0 ;sbb表示 运算结果 - CF的值
结果为:BX=0,AX=FFFFH,即结果为:FFFFH。
OF 标志
标志寄存器的第 11 位是OF,溢出标志位,该标志位记录了有符号数运算时的结果是否超出了所能表示的范围,如果超出,则, OF=1,否则,OF=0。
注意,该标志位和 CF 标志位的区别,CF 是针对无符号数运算时记录的标志,OF 是针对有符号数运算时记录的标志。
如:
mov al, 98
add al, 99
指令执行后,CF=0,OF=1。
CPU 执行 add等指令时,就包含了两种含义:无符号数运算和有符号数运算。
对于无符号数运算,99 + 98 没有产生进位,所以 CF=0。
对于有符号数运算,99 + 98 = 197,超出了8位寄存器所能保存的有符号数范围(-128~127),发生了溢出,所以 OF=1,同时,因为 SF 也会记录结果的正负,所以SF=1。
所以,对于有符号数运算,若发生溢出,结果则是不正确的。
DF 标志
标志寄存器的第 10 位是DF,方向标志位。该标志位在串处理指令中,控制每次操作后寄存器 SI 和 DI 的增减。
若 DF=0,每次操作后,SI 和 DI 递增。
若 DF=1,每次操作后,SI 和 DI 递减。
该标志位通过以下指令来设置:
cld ;置 DF = 0
std ;置 DF = 1
该标志位和串处理指令配合使用:
movsb
该串指令把 DS:[SI] 内存单元的字节型数据传送给 ES:[DI] 指向的内存单元中。
该指令执行完后,会根据 DF 的值对 SI 和 DI 进行相应的增减1.
movsw
该串指令和 movsb 指令功能一致, 只是操控的数据是字型数据,每次操作后,根据 DF 的值对 SI 和 DI 进行相应的增减2。
一般情况下,该串指令常和 rep 配合使用:
rep movsb
或
rep movsw
该指令相当于进行了以下操作:
s:movsb 或 movswloop s
所以, rep 指令的作用是根据 CX 的值,重复执行后面的串传送指令。相当于实现了 CX 个字节或字型数据的传送。
如:
assume cs:code, ds:datadata segmentdb 'Welcome to masm!'db 16 dup (0) ;把Welcome to masm!写入到该处
data endscode segmentstart:mov ax, datamov ds, axmov si, 0mov es, axmov di, 16mov cx, 16 ;设置循环的次数,即要传送的字节型数据的数量cld ;设置 DF=0rep movsb ;循环把 DS:[SI] 处的数据传送到 ES:[DI] 处;程序返回退出mov ax, 4c00hint 21h
code endsend start
对于标志寄存器,有些指令可以影响标志位,有些不可以,有些可以影响多个标志位,有些可以影响单个标志位。根据这些标志位,我们可以做很多有实际用途的功能。
CMP 指令
cmp 指令是比较指令,有两个操作对象,指令执行相当于做了减法,只是不保存结果,但会影响标志寄存器中相应的多个标志位。
cmp 操作对象a, 操作对象b
如:
mov ax, 8
mov bx, 3
cmp ax, bx ;相当于ax - bx,但结果不会改变ax,bx的值
指令执行后,ax = 8,所以cmp指令不影响操作对象的值,但会影响标志位:
ZF=0, PF=1, SF=0, CF=0, OF=0
通过该指令和相应的标志位,我们可以知道相应的比较结果,比较的结果一般有如下几种:
a = b
a <> b
a > b
a >= b
a < b
a <= b
对于无符号数的比较,根据以上结果情况,我们只需要分析以下标志位即可:
ZF=0,结果不为0,说明 a <> b
ZF=1,结果位0,说明 a = b
CF=1, 产生了借位值,说明 a < b
CF=0, 无借位,说明 a >= b
CF=0 且 ZF=0,无借位且结果不为0,说明 a > b
CF=1 或 ZF=1,有借位或结果为0,说明 a <= 0
对于有符号数的比较,需要关注的标志位有所不同,因为有符号数运算会影响符号标志位 SF 和溢出标志位 OF,所以除了CF不在关注外,还需要关注SF和OF标志,同时不能仅根据 SF 的正负来判断两个操作数的大小,需要配合使用来判断:
1、SF=1,OF=0说明结果没有溢出,即结果是正确的,同时结果为负,则 a < b
2、SF=1,OF=1说明结果有溢出,同时结果又为负,说明是溢出导致的结果为负,所以实际的结果其实是正,则 a > b
3、SF=0,OF=1说明结果有溢出,同时结果又为正,说明是溢出导致的结果为正,所以实际的结果其实是负,则 a < b
4、SF=0,OF=0说明结果没有溢出,同时结果为正,则 a >= b
通过以上分析,指令 CMP 可以判断两个数的比较结果,并影响相应的标志位。同时8086也提供了大量的条件转移指令来根据这些标志位进行转移:
对于无符号数来说,常用的转移指令有:
je 标号 ;等于则转移至标号处,根据标志位 ZF=1
jne 标号 ;不等于则转移至标号处,根据标志位 ZF=0
jb 标号 ;小于则转移至标号处,根据标志位 CF=1
jnb 标号 ;大于等于则转移至标号处,根据标志位 CF=0
ja 标号 ;大于则转移至标号处,根据标志位CF=0且ZF=0
jna 标号 ;小于等于则转移至标号处,根据标志位 CF=1 或 ZF=1
cmp指令常和条件转移指令结合使用,来实现类似 if~else 的功能:
如,实现查找以下数据中大于 3 的个数,保存到 ax 中:
assume cs:codedata segmentdb 1, 2, 3, 4, 5, 1, 2, 3, 3, 4, 7
data endscode segmentstart:mov ax, datamov ds, axmov bx, 0mov cx, 11mov ax, 0s:cmp byte ptr ds:[bx], 3jna nextinc axnext:inc bxloop smov ax, 4c00hint 21h
code endsend start
条件转移指令都是短转移指令,根据标号处的偏移地址的位移来转移的,所以,转移范围为:-128~127
更多条件转移指令可参考如下,注意有些指令的功能是一致的:
指令格式 | 判断标志位 | 转移说明 |
---|---|---|
JZ | ZF=1 | 等于0或相等则转移 |
JE | ZF=1 | 等于0或相等则转移 |
JNZ | ZF=0 | 不等于0或不相等则转移 |
JNE | ZF=0 | 不等于0或不相等则转移 |
JS | SF=1 | 为负则转移 |
JNS | SF=0 | 为正则转移 |
JO | OF=1 | 溢出则转移 |
JNO | OF=0 | 无溢出则转移 |
JP | PF=1 | 偶则转移 |
JPE | PF=1 | 偶则转移 |
JNP | PF=0 | 奇则转移 |
JPO | PF=0 | 奇则转移 |
JB | CF=1 | 小于或进位标志被置1则转移(无符号数) |
JNAE | CF=1 | 小于或进位标志被置1则转移(无符号数) |
JC | CF=1 | 小于或进位标志被置1则转移(无符号数) |
JNB | CF=0 | 不小于或大于等于或进位标志被置0则转移(无符号数) |
JAE | CF=0 | 不小于或大于等于或进位标志被置0则转移(无符号数) |
JNC | CF=0 | 不小于或大于等于或进位标志被置0则转移(无符号数) |
JBE | (CF或ZF)=1 | 小于等于则转移(无符号数) |
JNA | (CF或ZF)=1 | 小于等于则转移(无符号数) |
JNBE | (CF或ZF)=0 | 大于则转移(无符号数) |
JA | (CF或ZF)=0 | 大于则转移(无符号数) |
JL | (SF异或OF)=1 | 小于则转移(有符号数) |
JNGE | (SF异或OF)=1 | 小于则转移(有符号数) |
JNL | (SF异或OF)=0 | 大于等于则转移(有符号数) |
JGE | (SF异或OF)=0 | 大于等于则转移(有符号数) |
JLE | ((SF异或OF)或ZF)=1 | 小于等于则转移(有符号数) |
JNG | ((SF异或OF)或ZF)=1 | 小于等于则转移(有符号数) |
JNLE | ((SF异或OF)或ZF)=0 | 大于则转移(有符号数) |
JG | ((SF异或OF)或ZF)=0 | 大于则转移(有符号数) |
PUSHF 和 POPF
该指令为把标志寄存器中的值压栈和把栈中的数据转移至标志寄存器中,通过该指令我们可以对标志寄存器进行保存和恢复,同时还能对标志位进行相应更改:
如:
所有标志位都置0
pushf
pop ax
and ax, 0
push ax
popf
目录
上一章
下一章
我是如何学习Java的~标志寄存器及其应用相关推荐
- 超硬核的Java工程师分享,什么是Java?为什么我要做Java,我是如何学习Java的?
Java是啥 新手程序员通常会走入一个误区,就是认为学习了一门语言,就可以称为是某某语言工程师了.但事实上真的是这样吗?其实并非如此. 今天我们就来聊一聊,Java 开发工程师到底开发的是什么东西.准 ...
- sqlsever主库从库如何切换_超硬核的Java工程师分享,什么是Java?为什么我要做Java,我是如何学习Java的?...
Java是啥 新手程序员通常会走入一个误区,就是认为学习了一门语言,就可以称为是某某语言工程师了.但事实上真的是这样吗?其实并非如此. 今天我们就来聊一聊,Java 开发工程师到底开发的是什么东西.准 ...
- 零基础如何学习Java,这里分享一些技巧心得
现在我们都认为互联网成就了我们,但是真正能懂得互联网给我生活带来益处的人又有多少,我相信现在还有很多人都还停留在电脑白痴的阶段,但是我们身边开始出现了各类的IT专业术语,比如java的学习,这个问题呢 ...
- 学习 Java 的历程和体会『写给新手看,欢迎老司机批评和建议』
转载出处:https://blog.csdn.net/lw_power/article/details/52502698#commentBox Java 基础只能说熟悉,还达不到熟练,更谈不上精通.框 ...
- 学习Java的第十周
学习Java的第十周 表单标签 一.CSS介绍 二.CSS和HTML结合 2.1CSS和HTML结合之内联结合 2.2CSS与HTML结合之内部部结合 2.3CSS和HTML结合之外部结合 三.访问路 ...
- 即将实习的应届毕业生 学习java SpringMVC 数据库 知识总结
即将实习的应届毕业生 学习java SpringMVC 数据库 知识总结 1.Java语言的优点: 1)Java是纯面向对象语言 2)与平台无关性,一次编译到处运行 3)Java提供了狠多内置类库 4 ...
- 我学习 Java 的历程和体会(写给新手看,欢迎老司机批评和建议,持续更新中)
我学习 Java 的历程和体会(写给新手看,欢迎老司机批评和建议,持续更新中) 最初写这篇文章的时候,是在今年的 9 月中旬.今天,我想再写写这将近两个多月以来的感受. 在今年的 10 月我来到北京求 ...
- 软件测试学java,软件测试学习Java的内存模型
原标题:软件测试学习Java的内存模型 软件测试学习Java的内存模型 主内存与工作内存 定义程序中各个变量的访问规则. 规定JVM必须遵循的最小保证. 定义操作的偏序关系.Happens-Befor ...
- 对学习JAVA的总结 第一次课
2019独角兽企业重金招聘Python工程师标准>>> 这次课讲的是 java SE 的部分 刚开始学的时候觉得比较难,但是学习一段时间后觉得前面难的东西都变的简单了,每 ...
最新文章
- 牛!月入2w,95后送外卖的程序员,送餐途中改bug
- 虚拟化基础架构Windows 2008篇之1-虚拟化基础服务概述
- 神经网络的输出有方向吗?
- 查看coo_matrix的shape
- Altium designer中元器件库(SCHLIB)元件引脚上文字(标号)大小及距离边缘位置设置
- 聚集索引和非聚集索引的区别有哪些
- java clock计时_Java Clock类| systemDefaultZone()方法与示例
- Windows Server 2003 下安装Apache+Php+Mysql
- WinCE下音频频谱显示效果图
- java根据wait,notify,synchronize关键字自定义队列
- python条件语句代码例子_Python 炫技操作:条件语句的七种写法
- html5在线显示ofd文件,基于HTML5的OFD文件在线显示的方法以及装置制造方法及图纸...
- 【接口测试】Jmeter+ant安装及简单使用教程(集成)
- 微信小程序选项卡底线转换滑动动画
- 修改html颜色代码,JavaScript实现更改网页背景与字体颜色的方法
- 浏览器提示“此网站的安全证书有问题“,你还敢继续访问吗?
- Exception: ROM is missing for pong, see https://github.com/openai/atari-py#roms for instructions
- 渗透实战(周三):Ettercap·ARP毒化MITM中间人攻击
- 非802.11r的Fast Roaming
- 一段代码之仿LOL移动方式
热门文章
- 【今日CV 计算机视觉论文速览 第140期】Wed, 3 Jul 2019
- 计算机科学与技术文献翻译,计算机科学与技术外文文献翻译.doc
- Nginx无法启动 遇见unknown directive if(!-f in E:\xiangmu\nginx-1.14.0/conf/nginx.conf:28
- Linux中对lvm逻辑卷的管理
- 教育教学直播截图(未完待续)
- 运行错误:view size is not compatible with input tensor‘s size and stride (at least
- 反欺诈类优秀文章汇总
- 2022危险化学品生产单位安全生产管理人员考试题库模拟考试平台操作
- 财务会计基础(二)复式记账法
- 腾讯打击QQ宠物外挂颁布Q宠打工新规定(转)