《深入理解计算机系统》3.6控制

这章主要讲了条件语句,循环语句,switch语句在计算机中是如何实现的

条件码

除了整数寄存器,计算机还有保存最近算术和逻辑操作的条件码寄存器

条件码寄存器保存的是单个位的数据

举个例子if(a>2){},计算机会让a-2,这时候计算机会根据计算的结果自动变动条件码寄存器的值。最后根据一个条件码或多个条件码判断是否跳转,具体见后文。

这些条件码在计算机运算的时候根据最近的计算结果会自动的更改状态

例如某次运算结果为0,那么ZF会变成1,如果结果不为0,那么ZF会变成0

例如上面的操作都会改变条件码

有两类指令只为了改变条件码,而不改变其他寄存器,例如在比较两个数的大小的时候会用到这种指令

用于改变条件码的指令

下图中表示的是在使用该指令的时候操作数实际被用于什么样的运算,状态码就是被这次运算改变的.

访问条件码

条件码通常不会直接被读取,常用的使用方法有三种

  1. 根据条件码的组合,使用指令设置某个字节为0或1.
  2. 可以调整到程序的某个其他部分
  3. 可以有条件的传送数据

第一种情况用的指令被称为SET指令

注意图中的后缀不代表它是用于某个数据类型的.不要认为setb是操作字节的

SET指令的目的操作数是8个整数寄存器之一,或是一个字节大小的存储器,它会把一个字节设置为0或1.但如果想获得一个32位(4字节)结果,需把前24位清零.

例子

C语言中的a<b

其汇编为

未溢出情况下

Created with Rapha?l 2.1.4开始a &lt; b返回1a-b<0SF=1,OF=0,SF^OF=1结束返回0a-b>0SF=0,OF=0,SF^OF=0yesno

  1. start=>start: 开始
  2. end=>end: 结束
  3. cond1=>condition: a &lt; b
  4. ret1=>operation: 返回1
  5. ret0=>operation: 返回0
  6. op2=>operation: a-b<0
  7. op3=>operation: a-b>0
  8. result0=>operation: SF=0,OF=0,SF^OF=0
  9. result1=>operation: SF=1,OF=0,SF^OF=1
  10. start->cond1(yes)->ret1
  11. cond1(no)->ret0
  12. ret1->op2->result1->end
  13. ret0->op3->result0->end

溢出情况下

Created with Rapha?l 2.1.4开始a《b返回0a-b>0因为b是很小的负数SF=1,OF=1,SF^OF=0结束返回1a-b<0因为b是很大的正数SF=0,OF=1,SF^OF=1yesno

  1. start=>start: 开始
  2. end=>end: 结束
  3. cond=>condition: a《b
  4. ret1=>operation: 返回0
  5. ret0=>operation: 返回1
  6. op1_1=>operation: a-b>0
  7. op0_1=>operation: a-b<0
  8. op1_2=>operation: 因为b是很小的负数
  9. op0_2=>operation: 因为b是很大的正数
  10. result0=>operation: SF=1,OF=1,SF^OF=0
  11. result1=>operation: SF=0,OF=1,SF^OF=1
  12. start->cond(yes)->ret1->op1_1->op1_2->result0->end
  13. cond(no)->ret0->op0_1->op0_2->result1->end

跳转指令

跳转指令分为

  • 直接跳转,即跳转目标直接写在指令中比如图中的.L1
  • 间接跳转,从寄存器或存储器中获得地址并跳转
    • jmp *%eax//注意间接跳转需要有个*

图中所示的指令除了jmp其他都是条件跳转其配合条件码来决定是否跳转

条件跳转只能是直接跳转

跳转指定跳转的目标位置(Lable)有多中的编码方式

最常用的是PC相关

PC,Program Counter,程序计数器,总是指向CPU下一条执行的指令位置

这种方式编码,jmp 的操作数写的是跳转目标指令的地址减去PC中保存的值

例子

条件分支

条件语句常混合使用有条件和无条件跳转

条件传送指令

//可能要先看循环部分

故名思议该指令就是在一定条件下才执行数据转移

1995年PentiumPro才开始有条件传送指令,但是当时GCC为了向后兼容,默认不翻译出带条件传送指令的汇编代码

条件传送指令性能更好,但并不是绝对的

a,b图的作用是一样的,b图的代码跟接近汇编代码的样子

如果不使用带条件指令的汇编将可能会是这样

如果使用了

最后一个指令cmov(Condition move),l(less)

意思是如果x<y则把y-x设置为返回值

乱入的知识点

不明白这个知识写为什么要写在这

大概是说CPU使用流水线技术在取一台哦指令的时候,执行他前面一条指令的算术运算,也就是说在前一条指令未执行完成后一条工作任务就要拿到手上.对于条件判断,在运算完成之前是不知道下面的任务的,于是都靠.

原文写到处理器采用非常精密的 分支预测逻辑 试图猜测每条跳转指令是否会执行,而该预测的成功率是90%.

如果预测错误,那么丢掉它该跳转指令后所有指令已经做了的工作,然后在开始从正确位置处起始的指令去填充流水线.

指令

条件传送指令的传送条件是依赖于条件寄存器

该指令汇编器会自动根据寄存器判断数据类型,于是指令末尾不需要加l,w等

例子

当未使用条件传送指令编译器生成的代码

使用了传送指令编译器生成的代码

易知,使用了传送指令的代码,他把条件运算符中的then-expr和else-expr都计算了.这种多余的计算在某些时候会产生问题比如//只给例子

所以条件传送指令并不总是改善代码效率

循环

汇编中主要根据do-while循环编译而成,其他形式的循环只是在do-while版本的循环上稍作修改

while 循环

  1. while (test-expr)
  2. body-statement

do-while版:

  1. if(!test-expr)
  2. goto done;
  3. do
  4. body-statement
  5. while (test-expr);
  6. done;

goto版:

  1. t=test-expr;
  2. if(!t)
  3. goto done;
  4. loop:
  5. body-statement;
  6. t=test-expr;
  7. if(t)
  8. goto loop;
  9. done:

for循环

  1. for(init-expr;test-expr;update-expr)
  2. body-statement

do-while版

  1. init-expr;
  2. if(!test-expr)
  3. goto done;
  4. do {
  5. body-statement
  6. update-expr;
  7. } while (test-expr)
  8. done:

goto版

  1. init-expr;
  2. t = test-expr;
  3. if(!t)
  4. goto done;
  5. loop:
  6. body-staement
  7. update-expr;
  8. t = test-expr;
  9. if(t)
  10. goto loop;
  11. done:

switch

当switch的条件比较多,且被switch的值范围跨度大的时候就会用跳转表提高性能.

跳转表是保存了一堆代码段位置的数组

直接给书中的例子

右图中*jt[7]数组中保存的值都是&&开头,运算符&代表创建以后只想数据值得指针,&&代表创建一个只想代码位置的指针

汇编版:

来自为知笔记(Wiz)

时间: 2024-08-28 19:50:54

《深入理解计算机系统》3.6控制的相关文章

深入理解计算机系统9个重点笔记

引言 深入理解计算机系统,对我来说是部大块头.说实话,我没有从头到尾完完整整的全部看完,而是选择性的看了一些我自认为重要的或感兴趣的章节,也从中获益良多,看清楚了计算机系统的一些本质东西或原理性的内容,这对每个想要深入学习编程的程序员来说都是至关重要的.只有很好的理解了系统到底是如何运行我们代码的,我们才能针对系统的特点写出高质量.高效率的代码来.这本书我以后还需要多研究几遍,今天就先总结下书中我已学到的几点知识. 重点笔记 编写高效的程序需要下面几类活动: 选择一组合适的算法和数据结构.这是很

《深入理解计算机系统》第六周学习笔记

第四章 处理器体系结构 (一)知识点总结 一.Y86指令集体系结构 1.Y86处理器状态类似于IA32,有8个程序寄存器: %eax.%ecx.%edx.%ebx.%esi.%edi.%esp.%ebp.处理器的每个程序寄存器存储一个字.%esp被入栈.出栈.调用和返回指令作为栈指针. 2.3个一位的条件吗:ZF.SF.OF,它们保存最近的算术或逻辑指令所造成影响的有关信息.程序计数器PC存放当前正在执行指令的地址. 3.程序状态的最后一个部分是状态码stat,它表明程序执行的总体状态 4.Y8

深入理解计算机系统(4.2)---硬件的魅力

引言 这个系列已经很久没更新了,记得上一篇博文已经是三月份了,实在是抱歉.最近业余时间没有以前充裕了,因此更新一篇博文已经变成了一种奢侈.记得以前刚开始写的时候,最多的时候LZ一天写过3篇博文,现在想想,往事如梦. 好了,好不容易写一次,就不多说废话了,本文主要介绍一下硬件以及HCL语言的内容. 从疑问开始 首先,在介绍本文的内容之前,我们先来思考一个看似简单,却实际比较“高深”的问题.众所周知,计算机归根结底是在和0.1打交道,那么到底0和1是如何被计算机记住的呢? 怎么样,这个问题是不是有点

深入理解计算机系统读书笔记一 ---&gt; 计算机基础漫游

一.程序编译的不同阶段. 通常我们是以高级程序开发易于阅读的代码,我们通过语法规则推断代码的具体含义.但是计算机执行代码的时候就需要把代码解析成既定的可执行问题,计算机是如何处理的呢?这里以C语言hello.c文件为例来说明中间过程. #include <stdio.h> int main() { printf("hello world!\n"); } 先上张图. C语言源程序----预处理解析头文件和函数  --- 编译器解析成汇编语言 ---   翻译机器语言指令,打包

电子书 深入理解计算机系统.pdf

内容简介 和第2版相比,本版内容上*大的变化是,从以IA32和x86-64为基础转变为完全以x86-64为基础.主要更新如下: 基于x86-64,大量地重写代码,首次介绍对处理浮点数据的程序的机器级支持. 处理器体系结构修改为支持64位字和操作的设计. 引入更多的功能单元和更复杂的控制逻辑,使基于程序数据流表示的程序性能模型预测更加可靠. 扩充关于用GOT和PLT创建与位置无关代码的讨论,描述了更加强大的链接技术(比如库打桩). 增加了对信号处理程序更细致的描述,包括异步信号安全的函数等. 采用

第七章读书笔记《深入理解计算机系统》

第七章 读书笔记<深入理解计算机系统> 链接是将各种代码和数据部分收集起来并组合成为一个单一文件的过程,这个文件可被加载(或拷贝)到存储器并执行. 链接可以执行于编译时,也就是在源代码被翻译成机器代码时:也可以执行于加载时,也就是在程序被加载器加载到存储器并执行时:甚至执行于运行时,由应用程序来执行. 在早期的计算机系统中,链接是手动执行的.在现代系统中,链接是由叫链接器的自动执行的. 7.1 编译器驱动程序 1.大部分编译系统提供编译驱动程序:代表用户在需要时调用语言预处理器.编译器.汇编器

对找工作功不可没——评《深入理解计算机系统》

对找工作功不可没——评<深入理解计算机系统> 引子: 在我刚刚进入中科院计算所读研的时候,同宿舍的师兄便向我推荐了一本<深入理解计算机系统>,这本书从一个程序员的视角详细剖析了整个计算机系统,涵盖了组成原理.汇编语言.体系结构.操作系统.网络等计算机基础知识. 由于时间所限,我并没有立刻阅读,而是将其列入了找工作前的复习书单.2010年8月,我用了一个月的时间读完了这本书的原版<Computer System:A programmer's perspective>.后来

深入理解计算机系统(3.1)------汇编语言和机器语言

<深入理解计算机系统>第三章--程序的机器级表示.作者首先讲解了汇编代码和机器代码的关系,阐述了汇编承上启下的作用:接着从机器语言IA32着手,分别讲述了如何存储数据.如何访问数据.如何完成运算以及如何进行跳转.通过这些步骤,又告诉了我们分支语句.循环语句是怎么完成的,函数调用.栈帧结构以及递归过程.最后能通过编译器产生的汇编代码表示,我们要了解编译器和它的优化能力,知道编译器能为我们完成哪些工作. 而这篇博客我们将讲解汇编和机器代码的关系.首先下面一张图是C语言.汇编语言以及翻译过的机器语言

4.2《深入理解计算机系统》笔记(五)并发、多进程和多线程【Final】

该书中第11章是写web服务器的搭建,无奈对web还比较陌生.还没有搞明白. 这些所谓的并发,其实都是操作系统做的事情,比如,多进程是操作系统fork函数实现的.I/O多路复用需要内核挂起进程.多线程需要内核创建和挂起线程.我么只是使用以下操作系统的这项并发技术.但是我们必须处理一些存在问题. ●进程.用这种方法,每个逻辑控制流都是一个进程,由内核来调度和维护.因为进程有独立的虚拟地址空间,想要和其他流通信,控制流必须使用进程间通信(IPC). ●I/O多路复用.这种形式的并发,应用程序在一个进

《深入理解计算机系统》第七章 链接

<深入理解计算机系统>第七章 链接 链接是将各种代码和数据部分收集起来并组合成为一个单一文件的过程,这个文件可被加载(货被拷贝)到存储器并执行. 链接的时机 编译时,也就是在源代码被翻译成机器代码时 加载时,也就是在程序被加载器加载到存储器并执行时 运行时,由应用程序执行 链接器使分离编译称为可能. 链接是将各种代码和数据部分收集起来并组合成为一个单一文件的过程,这个文件可被加载(或拷贝)到存储器并执行. 链接可以执行于编译时,也就是在源代码被翻译成机器代码时:也可以执行于加载时,也就是在程序