1.正溢出与负溢出:

首先,一个正数与一个负数相加,不可能溢出,因为结果的绝对值一定小于两个加数的绝对值,既然两个加数能合理表示出来,结果一定也能合理表示出来。

其次,正溢出是由于两个很大的正数相加,导致符号位变成1的情况如0110+0011=1001(假设最大只能运算4位)

负溢出则是两个很小的负数相加,导致符号位变成0的情况,如1011(-5)+1011(-5)=10110->0110溢出,如1111(-1)+1111(-1)=11110->1110则没溢出。

因此,正溢出的判断标准是符号位或最高位有进位。

负溢出的判断标准是符号位和最高位只有一个发生了进位。符号位和最高位同时发生进位则没溢出。

注意,这里的最高位指的是去掉符号位后的最高位,即符号位后面一位。

可以结合上面列举的负溢出的例子理解。

2.条件码寄存器:

CPU维护着一组条件码寄存器,它们只有一个位,它们会记录最近的算术或逻辑操作带来的变化,常用的有:

CF:进位标志,代表最近的操作使最高位产生了进位,用于检测无符号操作的溢出。

ZF:零标志,代表最近的操作结果为0。

SF:符号标志,代表最近的操作结果为负数。

OF:溢出标志,代表最近的操作导致了正溢出或负溢出。

那么,系统是怎么根据操作来设置条件码寄存器的呢?以什么为判断基准?

比如系统用一条ADD指令完成了等价于t=a+b的功能,这时候会用以下表达式为判断基准,来设置条件码寄存器:

CF:  (unsigned)t < (unsigned)a  无符号溢出

ZF: (t==0)  零

SF: (t<0)    负数

OF: (a<0 == b<0) && (t<0 != a<0) 有符号溢出

解释下CF: CF可用于检测无符号操作的溢出,若t与a,b都无符号,则都>=0,若此时t

再解释下OF: OF代表发生了溢出,需要满足两个条件,一是两个加数符号相同,二是结果的符号要和任意一个加数相反。

leaq不是算术或逻辑指令,不会改变条件码。

逻辑操作中,XOR会使CF和OF标志被设置为0

移位操作中,CF为最后一个被移出的位,OF为0为什么?

INC和DEC会设置OF和ZF,但不会改变CF

3.CMP和TEST指令

CMP和TEST指令都有b,w,l,q版本,分别对应字节,字,双字,四字

CMP指令等价于SUB,区别就是它不会把计算结果更新到目的寄存器。CMP S1,S2会计算S2-S1并根据结果设置条件码。

TEST指令等价于AND,区别就是它不会把计算结果更新到目的寄存器。TEST S1,S2会计算S1&S2并根据结果设置条件码。

TEST指令可用来判断某个操作数是正数,负数还是0,比如 testq %rax,%rax

4.访问条件码

一般不直接访问条件码,而是根据条件码的组合设置某个字节为0或1,对应的就是SET指令。如下图:

其后缀不是用来标志操作数大小的,只是用来代表不同的比较条件的。

一个例子:

比较a(位于%rdi)和b(位于%rsi)时,汇编如下:(两者都是64位long)

comp:

cmpq  %rsi,%rdi

setl   %al

movzbl  %al,%eax

ret

此时比较的是%rdi(a)-%rsi(b),结果被设置到%al中,movzbl在设置%eax的高3个字节为0时,还会把%rax的高4个字节一起清0。

取其中的一条指令分析一下:

setl,代表有符号的

5.条件控制转移指令

如上图所示,跳转指令分有条件跳转和无条件跳转。

jmp是无条件跳转,在汇编代码中,它后面直接加标号,汇编器把它变为.o文件时,会将标号对应的目标地址编码为跳转指令的一部分。

它又分为直接和间接跳转,前者会直接把目标地址作为跳转指令的一部分,后者则从寄存器或内存中读出目标地址。

直接跳转的表现形式是直接在jmp后加标号,如jmp .L1。间接跳转的表现形式是*后面加操作数指示符,如jmp *%rax,又如jmp *(%rax)。

表中其它跳转指令都是条件跳转指令,条件跳转只能是直接跳转。

那么跳转指令在编码机器代码时是如何确定目标地址的呢?

如下:

          

左侧为一段汇编代码,右侧为对应的机器代码(.o)及反汇编代码。

跳转指令在变成机器代码时,最常用的编码方式是把目标地址和跳转指令后面那条指令对应的地址之差作为编码。当然,也有直接给出目标地址的编码方式。

右图中,.L2下面的第一条指令的地址为8,jmp的下一条指令地址是5(.L3是标号,不是指令),相差8-5=3,符合之前的规律。

这种表达方式的优点是表示的跳转目标都是相对值,因此当程序被重定位时(比如被链接后),改变的只是这段代码的绝对地址,但机器码仍可以不用变。

例子:

40042f: 74 f4    je xxxxxx

400431:  5d       pop %rbq

请写出xxxxxx的地址:

0xf4 = -12 , 12 = 0xc ,  400431-0xc = 400425

6.条件传送指令:

条件控制转移指令存在一种缺陷,处理器是通过流水线的方式处理指令的,在取一条指令的同时,可能同时在执行前一条指令的算术运算。因此需要预先确定好指令的执行序列。当出现条件跳转时,处理器会对分支进行预测,虽然准确率很高,但一旦预测失败,处理器需要丢掉它为此跳转指令后面所做的所有工作,重新填充流水线。这会导致程序性能下降。

而条件传送指令则是先把条件分支的多个值计算出来,比如说一个是a,一个是b,随后的操作是固定的,比如对a操作,++a什么的,此时若发现选的是b分支,则只需要b=a这么复制一下就行了,优势就在于无需为此丢掉跳转指令后面所做的工作,当然代价就是需要多做一次计算,因此条件传送指令的适用条件有限,编译器需要根据浪费的计算和分支预测错误导致的性能处罚中作权衡,然而实际上它无法很好地判断,因此,只有当两个表达式都十分容易计算时,编译器才会选用条件传送指令,有时候即使分支预测错误的开销更大,仍会选择条件控制转移指令。

以上是条件传送指令,和SET以及JMP一样,只有满足指定条件才能传送数据,源操作数可以是寄存器或内存地址,目的地是寄存器,它和MOV类指令类似,区别是指令名无需写上传送数据的长度(b,w,l,q),汇编器可从寄存器中推断出操作数长度(因为目的地不可能是内存地址,所以可以直接推断出)。

条件传送指令不支持单字节传送。

条件传送指令有使用限制,因为它必须计算所有的条件表达式,因此若任意一个有错误条件,会导致非法行为。

比如:

          

对于左侧这段C代码,汇编形式如右侧所示,因为即使xp计算为0,cmove仍会计算0(%rax)和*xp(%rax)的值,而此时xp为空指针,会发生引用空指针的错误。

7. do while和while的实现

首先看下do while的实现例子:

清晰易懂,无需解释。

while循环则有两种实现形式:

第一种,被称为跳转到中间的实现形式,如下:

第二种形式是guarded-do形式,如下:

  

第二种形式其实是一种更高级别的优化,它主要对初始值进行优化,大部分情况下,初始条件下的while的循环条件是满足的,此时对第一种情况,仍会做一个跳转(可以看到第一种形式的b图中的goto test必然会被执行),而第二种形式对此作了优化,它会先判断一下初始是否满足while循环条件,满足时继续执行不跳转,不满足时才跳转到结束段,这种手法相当于把while改造成了do while,比起do while,仅仅多了一层初始的判断。

8. for循环的实现:

for循环都能转换为while,转换思路如下图:

    

具体转换例子见书。

下面做一个练习:

将下面的for循环先转换为跳转到中间的while形式,再转换为guarded-do形式:

答案:

以第一种形式转换:

以第二种形式转换:

这里有个需要注意的地方,在由第一种向第二种转换时,开头的那个判断条件是n<=1,那是因为它只对初始条件判断就行,因为循环不退出条件为i<=n,而开始时i=2,所以开始时无法进入循环的条件是n<=1。

第二个练习:

答案:

A:直接翻译后如下图所示:

此时continue会直接跳过本次循环进入下次循环,相对的也会跳过i++,导致i一直不变,永远跳不出while循环。

改变方法:使用goto代替continue:

8.switch语句

switch通过跳转表实现,它是一个数组,里面每一项都是一个代码段的地址,GCC根据开关数量决定是否使用跳转表(如大于4个,且值跨度较小会用)

看一个switch的例子:

上面两张是switch语句的C语言使用及翻译,需要注意几点:首先&&在这里是一个C语言中的扩展运算符,用于创建一个指向某个代码位置的指针。

void *jt[7],jt是一个指针数组,这里unsigned long index=n-100配合if(index>6)可以把n的值限制在[100,106],因为n<100时n-100为负数,转换为unsigned后是个很大的正数。

下面左边那张是对应的汇编代码,注意jmp *.L4(,%rsi,8),这里是一个间接跳转,从.L4的地址为起始找到8*%rsi指代的索引对应的地址,乘8是因为一个内存地址占8个字节(64位)

右边那张是对应的跳转表,从中寻址到对应跳转目的地的地址,用间接跳转跳转过去。

原文:https://www.cnblogs.com/czw52460183/p/10067372.html

c语言rsi2010中制运行,汇编语言初探(控制类指令)-来自第三章3.6的笔记-P135-P163相关推荐

  1. Linux系统中后台运行java项目jar包指令

    Linux系统中后台运行java项目jar包指令 windows环境下后台运行jar包程序: https://blog.csdn.net/qq_36763419/article/details/109 ...

  2. 计算机软件中os具有什么功能,[计算机软件及应用]OS第三章1.ppt

    [计算机软件及应用]OS第三章1 基于时钟中断的抢占式优先权调度算法 当前进程 实时进程 调度时间 实时进程要求调度 时钟中断到来时 抢占式调度算法 立即抢占式优先权调度算法 新到达的外部事件提出中断 ...

  3. matlab中任意两边之和大于第三边,MATLAB教程第三章.ppt

    <MATLAB教程第三章.ppt>由会员分享,可在线阅读,更多相关<MATLAB教程第三章.ppt(34页珍藏版)>请在人人文库网上搜索. 1.MATLAB程序语言设计, ,第 ...

  4. 汇编语言(算术运算类指令总结)

    文章目录 一.进位和溢出标志 二.零标志.符号标志和奇偶标志 标志一览表 三.算术运算类指令 1.ADD指令 2.SUB指令 3.ADC和SBB指令 4.INC.DEC和NEG指令 加减法指令一览表 ...

  5. 计算机工作过程中 电压应稳定在,计算机组装与维修前三章测评卷.doc

    计算机组装与维修前三章测评卷 计算机组装与维修第一.二.三章测评卷 2011年10月17日 一.选择题(第小题1分,共40分) 1.USB2.0接口数据传输速率的理论值是 A.8Mbps B.480M ...

  6. Java语言高级(第四部分)File类与IO流 ->(个人学习记录笔记)

    文章目录 第六章 File类与IO流 1. File类 1.1 概述 1.2 构造方法 1.3 常用方法 获取功能的方法 绝对路径和相对路径 判断功能的方法 创建删除功能的方法 1.4 目录的遍历 2 ...

  7. clipse3.2/3.3中指定第三方包(JAR)和类路径(CLASSPATH)的几个方法(转做笔记)

    在Java类中,我们可以通过"import + 包名 + 类名"的方式引用第三方包(jar)或者第三方类(class),但你得告诉Java编译和运行环境到哪里去找这些库或者类,如果 ...

  8. 汇编语言 王爽 第四版 第三章 检测点3.2

    汇编语言 王爽 第四版 课后检测点 课后实验 持续更新~~ 检测点3.2 1 补全下面的程序,使其可以将10000H-1000FH中的8个字,逆序拷贝到20000H-2000FH中. mov ax,1 ...

  9. 汇编语言与微机原理/计算机组成原理第三章:寻址方式与数据传送

    一. 单选题(共8题,49.6分) (单选题)假设VAR为变量,指令"MOV BX, OFFSET VAR"的源操作数寻址方式是( ) A. 立即寻址 B. 直接寻址 C. 间接录 ...

最新文章

  1. 把项目放到码云上,通过git 进行项目管理
  2. 剑指offer 面试题三 找出数组中重复的数字
  3. java读取pi_(树莓派csi相机)使用Java从raspivid-stdout读取h...
  4. No result defined for action action.LoginAction and result success 问题解决
  5. vue路由匹配实现包容性_包容性设计:面向老年用户的数字平等
  6. delphi 第一个字符不能是小数点_元字符的详细解析
  7. 【机器学习】知识框图总结
  8. java基础——java基本运算
  9. mysql内连接和交叉连接_MySQL中的内连接、外连接、交叉连接
  10. 使用adb安装apk
  11. 计算机安装系统后鼠标无法使用,重装系统后鼠标不能用
  12. VOA 2011-2-16
  13. 【英语语法入门】 第31讲 [被动语态 (1)]被动态的构成和含义
  14. 一些AUTOSAR会议论坛的介绍(附资料下载)
  15. MacOS Monterey 12.4 (21F79) OC 0.8.0 / Cl 5146 / PE 三分区原版黑苹果镜像
  16. Unreal Engine 4 渲染目标(Render Target)教程 之 实现雪地足迹(上)
  17. 电厂数字化进阶之路(三):时代的召唤
  18. Type-C扩展坞常用料号大全|音视频芯片|cc协议芯片|PD芯片|HUB芯片|网口芯片|音频芯片
  19. [python]bokeh学习总结——QuickStart
  20. Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] ...

热门文章

  1. 初探QQ空间本地安全问题!
  2. 服务器IMM2实战介绍
  3. .php文件是病毒吗,php病毒
  4. 30个 英文SEO内容推广平台整理
  5. Hdoj 2188.悼念512汶川大地震遇难同胞——选拔志愿者 题解
  6. python控制已经打开的浏览器_使用python+selenium控制手工已打开的浏览器
  7. 月赚千刀的国外联盟Lead项目,实操拆解
  8. /storage/sdcard0, /sdcard, /mnt/sdcard ,/storage/emulated/legacy 的区别
  9. 利用XSS漏洞实现键盘记录器
  10. 配置yun源和在虚拟机中安装JDK