汇编语言之标志寄存器



1、标志寄存器

CPU内部的寄存器中,有一种特殊的寄存器(对于不同的处理机,个数和结构都可能不同)具有以下3种作

用:

1. 用来存储相关指令的某些执行结果。

2. 用来为CPU执行相关指令提供行为依据。

3. 用来控制CPU的相关工作方式。

这种特殊的寄存器在8086CPU中,被称为标志寄存器。8086CPU的寄存器,在前面已经学过13个了,现

在学习最后一个寄存器FR-标志寄存器。

FR与其它寄存器不一样,其它寄存器是用来存放数据的,都是整个寄存器具有一个含义,而FR寄存器是按位

起作用的,也就是说它的每一位都有专门的含义,记录特定的信息。

8086CPU的FR寄存器的结构如下图所示:

FR的第1、3、5、12、13、14、15位是空白位,在8086CPU中没有使用,不具有任何意义,而第0、2、

4、6、7、8、9、10、11位都具有特殊的含义。


2、CF标志

7.1 CF标志

FR的第0位是CF,进位标志位。一般情况下,在进行无符号数运算的时候,它记录了运算结果的最高有效位

向更高位的进位值,或从更高位的借位值。

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

存在的第N位,就是相对于最高有效位的更高位,如下图所示:

 

我们知道,当两个数据相加的时候,有可能产生从最高有效位向更高位的进位,比如,两个8位数据:98H+

98H,将产生进位,这个进位值就用CF标志位来保存。

比如,下面的指令:

Mov al, 98H

Add al, al

执行后,计算结果为130H,al=30H,CF=1,CF记录了从最高有效位向更高位的进位值。

两数相加,如果产生了进位,则CF=1,如果没有产生进位,则CF=0。

 

当两个数据做减法的时候,有可能向更高位借位,比如,两个8位数据:97H-98H,将产生借位,借位后相

当于计算197H-98H,而FR的CF标志位也可以用来记录这个借位值。

比如,下面的指令:

Mov al, 97H

Sub al, 98H

执行后,计算结果为197H-98H=ffH,al=ffH,CF=1,CF记录了向更高位的借位值。

两数相减,如果产生借位,则CF=1,如果没有产生借位,则CF=0。


3、adc指令

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

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

功能:操作对象1=操作对象1+操作对象2+CF

例1:mov ax, 1

      Add ax, ax    ;结果:ax=2,没有产生进位值,CF=0。

      Adc ax, 3     ;结果:ax=ax+3+CF=2+3+0=5。

例2:mov al, 98H

      Add al, al    ;结果=130H,产生了进位值,CF=1,al=30H。

      Adc al, 3    ;结果:al=al+3+CF=30H+3+1=34H。

可以看出,adc指令比add指令多加了一个CF位的值,为什么要加上CF的值呢?CPU为什么要提供这样一

条指令呢?

我们来看一下两个数据:0198H和0183H是如何相加的,见下图:

 

可以看出,加法可以分两步来进行:1.低位相加(98+83)。2.高位相加再加上低位相加产生的进位值(1+1

+1)。看来CPU提供adc指令的目的,就是来进行加法的第二步运算的。用adc指令和add指令相配合就可以

对更大的数据进行加法运算。

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

因为两个数据的位数都大于16位,用add指令无法进行计算,我们将计算分两步进行,先将低16位

(F000H和1000H)相加,然后将高16位(1EH和20H)和进位值相加,代码如下:

Mov ax, 1eH

Mov bx, f000H

Add bx, 1000H    ;低16位相加,结果:f000H+1000H=10000H 产生了进位值,CF=1,bx=0。

Adc ax, 20H    ;高16位相加,结果:ax=ax+20H+CF=1eH+20H+1=3fH。

最终结果:ax=3fH,bx=0,1EF000H+201000H=3f0000H。

Adc指令执行后,也可能产生进位值,所以也会对CF位进行设置,由于有这样的功能,我们就可以对任意大

的数据进行加法运算。

例4:计算1EF0001000H+2010001EF0H,结果放在ax(最高16位),bx(次高16位),cx(低16位)

中。

计算分3步进行:

1.     先将低16位(1000H和1EF0H)相加,完成后,CF记录本次相加的进位值。

2.     再将次高16位(F000H和1000H)和CF(来自低16位的进位值)相加,完成后,CF记录本次相加

的进位值。

3.最后最高16位(1EH和20H)和CF(来自次高16位的进位值)相加,完成后,CF记录本次相加的进位

值。

代码如下:

Mov ax, 1eH

Mov bx, f000H

Mov cx, 1000H

Add cx, 1ef0H    ;低16位相加,结果:1000H+1ef0H=2ef0H,没有产生进位值,CF=0,cx=2ef0H。

Adc bx, 1000H    ;次高16位相加,结果:f000H+1000H+0=10000H,产生进位值,CF=1,bx=0。

Adc ax, 20H    ;最高16位相加,结果:ax=ax+20H+CF=1eH+20H+1=3fH,没有产生进位,CF=0。

最终结果:ax=3fH,bx=0,cx=2ef0H。1EF0001000H+2010001EF0H=3F00002EF0H。


4、sbb指令

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

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

功能:操作对象1=操作对象1-操作对象2-CF。

Sbb指令执行后,将对CF进行设置,利用sbb指令和sub指令配合使用可以对任意大的数据进行减法运算。

例1:计算3E1000H-202000H,结果放在ax(高16位),bx(低16位)。

计算分两步进行,先将低16位(1000H和2000H)相减,然后将高16位(3EH和20H)和借位值相减,

代码如下:

Mov bx, 1000H

Mov ax, 3eH

Sub bx, 2000H    ;低16位相减,结果:1000H-2000H=11000H-2000H=f000H,产生了借位值,

                    CF=1,bx=f000H。

Sbb ax, 20H    ;高16位相减,结果:ax=ax-20H-CF=3eH-20H-1=1dH,没有产生借位值,CF=0。

最终结果:ax=1dH,bx=f000H,3E1000H-202000H=1DF000H。

例2:计算6E4F0031C0H-1FA2002700H。结果放在ax(最高16位),bx(次高16位),cx(低16

位)。

计算分3步进行:

1. 先将低16位(31C0H和2700H)相减,完成后,CF记录本次相减的借位值。

2. 再将次高16位(4F00H和A200H)和CF(来自低16位的借位值)相减,完成后,CF记录本次相减的

借位值。

3. 最后将最高16位(6EH和1FH)和CF(来自次高16位的借位值)相减,完成后,CF记录本次相减的借

位值。

代码如下:

Mov ax, 6eH

Mov bx, 4f00H

Mov cx, 31c0H

Sub cx, 2700H    ;低16位相减,结果:31c0H-2700H=ac0H,没有产生借位值,CF=0,cx=ac0H。

Sbb bx, a200H    ;次高16位相减,结果:14f00H-a200H=ad00H,产生借位值,CF=1,bx=ad00H。

Sbb ax, 1fH    ;最高16位相减,结果:ax=ax-1fH-CF=6eH-1fH-1=4eH,没有产生借位值,CF=0。

最终结果:ax=4eH,bx=ad00H,cx=ac0H,6E4F0031C0H-1FA2002700H=4EAD000AC0H。

 

 


5、ZF标志

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

如果(假),结果非0,那么ZF=0。

对于ZF的值,我们可以这样来看:在计算机中1表示逻辑真,表示肯定,所以当结果为0的时候,ZF=1;在

计算机中0表示逻辑假,表示否定,所以当结果不为0的时候,ZF=0。

下面的指令:

Mov ax, 5

Sub ax, ax

执行后,结果为0,表示真,则ZF=1。

Mov ax, 5

Sub ax, 1

执行后,结果不为0,表示假,则ZF=0。


6、cmp指令

Cmp是比较指令,它的功能相当于sub指令,只是不保存结果。Cmp指令执行后,将对标志寄存器产生影

响,其它相关指令通过识别这些被影响的标志位来得知比较结果。

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

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

Cmp指令执行后,依据标志位的值就可以看出比较结果。

比如,cmp ax, bx执行后:

如果ZF=1,说明ax=bx,因为ax-bx=0,那么ax必定等于bx。

如果ZF=0,说明ax≠bx,因为ax-bx≠0,那么ax与bx必定不相等。

如果CF=1,说明ax<bx,因为ax-bx产生了借位,那么ax必定小于bx。

如果CF=0,说明ax≥bx,因为ax-bx没有产生借位,那么ax必定大于或等于bx。

如果CF=0,并且ZF=0,说明ax>bx,因为ax-bx没有产生借位,并且ax-bx≠0,那么ax必定大于bx。

如果CF=1或ZF=1,说明ax≤bx,因为ax-bx产生了借位,又或者ax-bx=0,那么ax必定小于或等于

Bx。

 


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


转移指的是它能够修改IP,而条件指的是它可以根据某种条件,决定是否修改IP,所有条件转移指令都是短

转移,转移的位移范围为﹣128~127。

大多数条件转移指令都检测标志寄存器的相关标志位,根据检测的结果来决定是否修改IP,它们所检测的标

志位都是被cmp指令影响的那些表示比较结果的标志位。

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

指令    检测的相关标志位          与cmp配合使用的逻辑含义

Je      如果ZF=1则转移               如果等于则转移

Jne    如果ZF=0则转移                如果不等于则转移

Jb      如果CF=1则转移              如果低于则转移

Jnb    如果CF=0则转移               如果不低于则转移

Ja      如果CF=0且ZF=0则转移       如果高于则转移

Jna    如果CF=1或ZF=1则转移       如果不高于则转移

以上这些条件转移指令是根据检测相关的标志位来决定是否转移,比如:je是检测ZF的值来决定是否转移,

如果ZF=1则转移,至于根据逻辑含义来决定是否转移,则需要与cmp指令配合使用,这个在下一节会讲到。


8、cmp与条件转移指令配合使用

上一节介绍的条件转移指令,所检测的标志位都是cmp指令进行无符号数比较的时候,记录比较结果的标志

位,比如,je检测ZF位,当ZF=1时转移,如果在je前面使用了cmp指令,那么je对ZF的检测,实际上是间

接地检测cmp的比较结果是否为两数相等。

请看下面一段代码:

Cmp ax, bx

Je s

Add ax, bx

Jmp short ok

  S:add ax, ax

Ok: …

上面的代码执行时,如果ax=bx,则cmp ax, bx使ZF=1,而je检测ZF是否为1,如果为1,则转移到标号

S处执行指令add ax, ax,我们也可以这样说,cmp比较ax, bx后所得到的相等的结果使得je指令进行转移,这

种说法很好地体现了je指令的逻辑含义,即“相等则转移“。

“相等则转移”这种逻辑含义是通过和cmp指令配合使用来体现的,我们用cmp指令与条件转移指令配合使

用的时候,不必再考虑cmp指令对相关标志位的影响和je等指令对相关标志位的检测,因为相关的标志位只是为

Cmp和je等指令传递比较结果,我们可以直接考虑cmp与je等指令配合使用时,表现出来的逻辑含义。

请看下面的指令:

Cmp byte ptr [bx], 8    ;和8比较

Je 标号                 ;如果等于则转移

Cmp byte ptr [bx], 8    ;和8比较

Jne 标号                ;如果不等于则转移

Cmp byte ptr [bx], 8    ;和8比较

Jb 标号                 ;如果低于则转移

Cmp byte ptr [bx], 8    ;和8比较

Jnb 标号                ;如果不低于则转移

Cmp byte ptr [bx], 8    ;和8比较

Ja 标号                 ;如果高于则转移

Cmp byte ptr [bx], 8    ;和8比较

Jna 标号                ;如果不高于则转移

上面的指令,用[bx]中的数值和8比较,“如果怎么怎么样则转移”,我们在修改游戏时,可以根据这些逻辑含

义(即:如果怎么怎么样则转移),选择合适的条件转移指令。


9、其它标志位

标志寄存器的大部分标志位,我们都不必深入地去学习,因为这和修改游戏没有多大关系,我们只需简单了解

一下即可,FR一共有9个标志位,前面已学习了ZF和CF这两个标志位,现在讲讲余下的7个标志位。

PF:奇偶标志位。它记录相关指令执行后,其结果的所有二进制位中1的个数是否为偶数,如果(真),1的

个数为偶数,PF=1,如果(假),1的个数为奇数,PF=0。

比如,某些指令执行后,其结果二进制值为01001011,有4(偶数)个1,则PF=1;某些指令执行后,其

结果二进制值为00001011,有3(奇数)个1,则PF=0。

SF:符号标志位。它记录相关指令执行后,其结果是否为负,如果(真),结果为负,SF=1,如果(假),结

果非负,SF=0。

OF:溢出标志位。一般情况下,OF记录了有符号数运算的结果是否发生了溢出,如果(真),发生了溢出,

OF=1,如果(假),没有发生溢出,0F=0。

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

的范围是多少呢?对于8位的有符号数据,机器所能表示的范围就是﹣128~127;对于16位的有符号数据,机器

所能表示的范围就是﹣32768~32767。如果运算结果超出了机器所能表达的范围,将产生溢出。

比如,指令:

Mov al, 98

Add al, 99

执行后,al=98+99=197,197超出了机器所能表示的8位有符号数的范围:﹣128~127,所以产生了溢出。

DF:方向标志位。在串处理指令中,控制每次操作后SI、DI的增减。

DF=0,每次操作后SI、DI递增;DF=1,每次操作后SI、DI递减。

DF标志位与串传送指令(movsb、movsw)有关,而串传送指令与游戏修改无关,所以就不讲解了。

TF:跟踪标志位。用于程序调试。

如果TF=1,则CPU处于单步执行指令的工作方式,此时,每执行完一条指令,就显示CPU各个寄存器的当

前值及CPU将要执行的下一条指令。如果TF=0,则处于连续工作模式。

AF:辅助进位标志位。在下列情况下,AF的值被设置为1,否则其值为0。

1. 在字操作时,发生低字节向高字节进位或借位时。

2. 在字节操作时,发生低4位向高4位进位或借位时。

IF:中断允许标志位。用来决定CPU是否响应CPU外部的可屏蔽中断发出的中断请求,当IF=1,响应中断

请求,当IF=0,不响应中断请求。

 


10、lea和nop指令

Lea为有效地址传送指令。

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

功能:将源操作数给出的有效地址传送到指定的寄存器中。

说明:操作对象1为目的操作数,可为任意一个16位的通用寄存器,操作对象2为源操作数,可为地址表达

式。

比如,指令:

Lea ax, [217a]

执行后,ax=217aH。

Lea ax, [bx+si+200]

执行后,ax= bx+si+200H。

 

Nop为空操作指令。格式:nop。

功能:本指令不产生任何结果,仅消耗几个时钟周期的时间,接着执行后续指令,常用于程序的延时等。

在修改游戏的时候,可用于锁定某些数据的数值。

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/292655.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

web网页的表单排版利器--960css

表单排版样式 960css 前言 一般web网页的表单排版,大家都习惯用table排版,自己需要根据实际需要去定义TR和TD,很多时候对于TD的高宽度、是否合并行,合并列,都要去做一些处理,这些都是比较繁琐的工作。找到一…

c语言将十进制转化为二进制算法_base64算法初探即逆向分析

算法分析虽说base64严格意义上来说并不能算是加密算法,但的确应用方面来说还算是比较广,在CTF的算法逆向中Base系列算是也比较常见的,萌新刚开始学算法,就以base64为例,对该算法进行一个简单的分析。简单来说&#xff…

新功能抢先看!Windows 11 2022 版全新 ISO 镜像来了+下载

面向 Dev 频道的 Windows 预览体验成员,微软现已发布 Windows 11 操作系统全新 ISO 镜像文件,此版本 ISO 镜像整合了自 Build 22449 至 Build 22533 的所有功能。文件名称:windows11_insiderpreview_client_x64_zh-cn_22533.iso 文件大小: 4.64 GB MD5:…

这是哪里来的小妖精!!!

1 或许小鸟依人就是怎么来的吧2 果然球体运动全靠弹。。3 小猫咪从爬猫架下来时的样子萌爆了....4 这猫也是很配合了~5 以后请不要说“有朝一日”,请说“下周五晚七点我请你吃火锅”,“三分钟后我给你打钱”,“现在我就喜欢你”。6 内容来源于…

汇编语言之常见的汇编指令

1、常见汇编指令 1. 传送指令(4个):mov、push、pop、lea。2. 转移指令(8个):call、jmp、je、jne、jb、jnb、ja、jna。3. 运算指令(7个):add、sub、mul、div、adc、sbb、c…

java list 初始化_Java新特性:数据类型可以扔掉了?

在很久很久以前,我们写代码时要慎重的考虑变量的数据类型,比如下面这些: 枚举:尽管在 JDK 5 中增加了枚举类型,但是 Class 文件常量池的 CONSTANT_Class_info 类型常量并没有发生任何语义变化,仍然是代表一…

Kubernetes应用程序开发认证(CKAD) 经验分享

众所周知,Kubernetes在容器编排器大战中脱颖而出后,从2020年以来变得越发的火热。那么云原生计算基金会(CNCF)联合Linux基金会就适时的推出了皆在考察相关从业者对Kubernetes的运维和开发知识了解程度的认证考试,分别是…

【数据结构入门精讲 | 第十九篇】考研408、企业面试图专项练习(二)

在上一篇中我们进行了图的专项练习,在这一篇中我们重点探讨图的编程专项习题。 目录 R7-1 城市间紧急救援R7-2 地铁一日游R7-3 最小生成树的唯一性R7-4 网红点打卡攻略R7-5 畅通工程之最低成本建设问题R7-6 寻宝图R7-7 逆散列问题R7-8 任务调度的合理性R7-9 关键活动…

判断点在多边形内

2019独角兽企业重金招聘Python工程师标准>>> 0.前言 最近不断遇到类似的几何位置问题,一直没有花时间去总结,本文总结了我常用点跟多边形的位置判断方法以及代码。希望能够对大家有所帮助。 文中所指的多边形均为凸多边形,一些描…

Centos6.5使用ELK(Elasticsearch + Logstash + Kibana) 搭建日志集中分析平台实践

Centos6.5安装Logstash ELK stack 日志管理系统概述:日志主要包括系统日志、应用程序日志和安全日志。系统运维和开发人员可以通过日志了解服务器软硬件信息、检查配置过程中的错误及错误发生的原因。经常分析日志可以了解服务器的负荷,性能安全性&#…

k8s 手动恢复redis 集群_二进制手动部署k8s-1.14高可用集群(二、集群部署)

1. CA证书(任意节点)1.1 安装cfsslcfssl是非常好用的CA工具,我们用它来生成证书和秘钥文件 安装过程比较简单,如下:# 下载 $ mkdir -p ~/bin $ wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 -O ~/bin/cfssl $ w…

实现DDD领域驱动设计: Part 1

原文链接: https://dev.to/salah856/implementing-domain-driven-design-part-i-5a72简单的代码!踢足球很简单,难的是踢简单的足球。— 克鲁伊夫如果我们将这句话用到编程上,我们可以说;写代码很简单,难的是写简单的代…

XE5 Android 开发实现手机打电话和发短信 [转]

其实都可以通过intent和URI调用系统功能.Windows程序员可以理解成是ShellExecute.这个是万金油.可以有调用各种功能.后面会介绍. 1.短信息.很简单 方法a.不使用Intent而是直接发短信. smsManager对应的Delphi代码应该是: usesAndroidapi.JNI.JavaTypes,Androidapi.JNI.Telephon…

安装程序无法创建新的系统分区也无法定位现有分区的解决方法

2019独角兽企业重金招聘Python工程师标准>>> 在安装Windows7时,想必有很多人都安碰到这样的情况吧!在安装界面里选择安装时,却出现“安装程序无法创建新的系统分区,也无法定位现有系统分区” 网上提供的另外解决方法大全&#xff…

python多线程读取数据库数据_Python基于多线程操作数据库相关知识点详解

Python基于多线程操作数据库相关问题分析 本文实例分析了Python多线程操作数据库相关问题。分享给大家供大家参考,具体如下: python多线程并发操作数据库,会存在链接数据库超时、数据库连接丢失、数据库操作超时等问题。 解决方法&#xff1a…

IDA64 Fatal error before kernel init

http://www.tuicool.com/articles/7FZVZna 第一次看到这个错误还以为是修改文件导致的,但是觉得又不大像,因为在Win7底下是完全正常的。搜索了一下才发现是由于插件导致的: NOTE3: You get a “Fatal error before kernel init” when trying…

Android安全与逆向之在ubuntu上面搭建NDK环境

1、下载Android NDK自解压包, 官方地址:https://developer.android.com/ndk/downloads/index.html#download下载:$ wget -c http://dl.google.com/android/ndk/android-ndk-r10e-linux-x86_64.bin 2、解压, 将Android NDK压缩包…