深入理解计算机系统(第3版) 第三章 程序的机器级表示(1)

1.机器代码

计算机执行机器代码,用字节序列编码低级的操作,包括数据处理、管理内存、读写存储设备上的数据,以及利用网络通信。

编译器基于编程语言的规则、目标机器的指令集和操作系统遵循的惯例,经过一系列的阶段生成机器代码。

汇编代码是机器代码的文本表示,给出程序中的每一条指令,然后GCC调用汇编器和链接器,根据汇编代码生成可执行的机器代码。

 

2.机器级代码

计算机系统使用了多种不同形式的抽象,利用更简单的抽象模型来隐藏实现的细节。

对于机器级编程来说,有两种抽象尤为重要,第一种是由指令集体系结构或指令集架构(instructino set architecture,ISA)来定义机器级程序的格式和行为,它定义了处理器状态、指令的格式,以及每条指令对状态的影响。大多数ISA,包括x86_64,将程序的行为描述成好像每条指令都是按顺序执行的,一条指令结束后,下一条再开始。处理器的硬件远比描述的精细复杂,它们并发地执行许多指令,但是可以采取措施保证整体行为与ISA指定的顺序执行的行为完全一致。第二种抽象是,机器级程序使用的内存地址是虚拟地址,提供的内存模型看上去是一个非常大的字节数组。存储器系统的实际实现是将多个硬件存储器和操作系统软件组合起来。

 

3.汇编代码

在整个编译过程中,编译器会完成大部分的工作,将把用C语言提供的相对比较抽象的执行模型表示的程序转化成处理器执行的非常基本的指令。汇编代码表示非常接近于机器代码,与机器代码的二进制格式相比,汇编代码的主要特点是它用可读性更好的文本格式表示。能够理解汇编代码以及它与原始C代码的联系,是理解计算机如何执行程序的关键一步。

 

4.操作数指示符

大多数指令有一个或多个操作数,指示出执行下一个操作中要使用的源数据值,以及放置结果的目标位置。源数据值可以以常数的形式给出,或是从寄存器或内存中读出。结果可以存放在寄存器或内存中。

操作数有三种,

第一种类型是立即数,用来表示常数值。

第二种类型是寄存器,它表示某个寄存器的内容;可以将寄存器集合看成一个数组,用寄存器标识符作为索引。

第三种类型是内存引用,它会根据算出来的地址(通常称为有效地址)访问某个内存地址。因为将内存看作一个非常大的字节数组。

 

5.数据传送指令

最频繁使用的指令是将数据从一个位置复制到另一个位置的指令。

操作数表示的通用性使得一条简单的数据传送指令能够完成在许多机器中要好几条不同指令才能完成的功能。

 

6.控制

到目前为止,我们只考虑了直线代码的行为,也就是指令一条接着一条顺序地执行。

C语言中的某些结构,比如条件语句、循环语句和分支语句,要求有条件的执行,根据数据测试的结果来决定操作执行的顺序。机器代码提供两种基本的低级机制来实现有条件的执行:测试数据值,然后根据测试的结果来改变控制流或数据流。

 

7.条件码

除了整数寄存器,CPU还维护着一组单个位的条件码寄存器,它们描述了最近的算术或逻辑操作的属性。可以检测这些寄存器来执行条件分支指令。

 

8.跳转指令

正常执行的情况下,指令按照它们出现的顺序一条一条地执行,跳转指令会导致执行切换到程序中一个全新的位置。在汇编代码中,这些跳转的目的地通常用一个标号指明。

理解跳转指令的目标如何编码,对研究链接非常重要。汇编器,以及后来的连接器,会产生跳转目标的适当编码。跳转指令有几种不同的编码,但是最常用的都是PC相对的。也就是,它们会将目标指令的地址与紧跟在跳转指令后面的那条指令的地址之间的差作为编码。这些地址偏移量可以编码为1、2或4个字节。第二种编码方法是给出‘绝对’地址,用4个字节直接指定目标。汇编器和链接器会选择适当的跳转目标编码。

 

9.用条件传送来实现条件分支

实现条件操作的传统方法是通过使用控制的条件转移。当条件满足时,程序沿着一条执行路径执行,而当条件不满足时,就走另一条路径。这种机制简单而通用,但是在现代处理器上,它可能会非常低效。

一种替代的策略是使用数据的条件转移。这种方法计算一个条件操作的两种结果,然后再根据条件是否满足从中选取一个。只有在一些受限制的情况下,这种策略才可行,但是如果可行,就可以用一条简单的条件传送指令来实现它,条件传送指令更符合现代处理器的性能特征。

为了理解为什么基于条件数据传送的代码会比基于条件控制转移的代码性能要好,我们必须了解一些关于现代处理器如何运行的知识。处理器通过使用流水线来获得高性能,在流水线中,一条指令的处理要经过一系列的阶段,每个阶段执行所需操作的一小部分(例如,从内存取指令、确定指令类型、从内存读数据、执行算术运算、向内存写数据,以及更新程序计数器)。这种方法通过重叠连续指令的步骤来获得高性能。处理器采用非常精密的分支预测逻辑来猜测每条跳转指令是否会执行,只要它的猜测还比较可靠(现代微处理器设计试图达到90%以上的成功率),指令流水线中就会充满着指令。另一方面,错误预测一个跳转,要求处理器丢掉它为该跳转指令后所有指令已做的工作,然后再开始从正确位置处起始的指令去填充流水线(这样一个错误预测会招致很严重的惩罚,浪费大约15~30个时钟周期,导致程序性能严重下降)。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值