深入理解计算机系统 1

第一章 计算机系统漫游

1.1 信息就是 位+上下文

hello程序的生命周期就是从一个源程序(源文件)开始的,即程序员利用编辑器创建并保存的文本文件,文件名是hello.c .源程序实际是一个由值10组成的位(bit)序列,八个位被组成一组,称为字节.每个字节表示程序中某个文本字符.

大部分的现代系统都是用ASCII标准来表示文本字符,这种方法实际上是用一个唯一的单字节大小的整数值来表示每个字符.

hello.c程序以字节序列的方式存储在文件中,每个字节都有一个整数值,而该整数值对应于某个字符.注意,每个文本行都是以一个不可见的换行符‘\n'来结束的.呀对应的整数值是10.这样子由ascii字符构成的文件称为文本文件,所有其他文本文件都称为二进制文件.

hello.c的表示方法说明了一个基本道理:系统中的所有的信息,包括磁盘文件,存储器中的程序,存储器存放的用户数据以及网络上面传送的数据,都是由一串位表示的.区分不同数据的唯一方法就是我们读到这些数据对象时的上下文.比如 在不同的上下文,一个同样的字节序列可能表示一个整数,浮点数,等等.

作为程序员,我们需要了解数字的机器表示方式,因为他们与实际的整数和实数是不同的,他们是对真值的无限近似值,有时候会有意想不到的行为表现.这方面基本原理在第二章详细论述.

旁注,c语言的起源

贝儿实验室研究的,有什么特点呢

unix操作系统息息相关,

小而简单

是为实践目的设计的.

 

1.2 程序被其他程序翻译成不同的格式

hello 程序的生命周期是从一个高级c语言程序开始的.因为这种形式能够被人读懂,然而,为了在系统上运行hello.c程序,每条c语句都必须被其他程序转化成一系列的低级程序语言指令.然后这些指令按照一种称为可执行目标程序的格式打好包,并以二进制磁盘文件的形式存储起来,目标程序也可称为可执行目标文件.

unix系统上,从源文件到目标文件的转化是由编译器驱动程序完成的:

unix>gcc-o hello hello.c

在这里 gcc编译器驱动程序读取源程序文件hello.c,并把它翻译成一个可执行目标文件hello .

这个翻译的过程可分为四个阶段完成,执行这四个阶段的程序(预处理器,编译器,汇编器,和链接 器)一起构成了编译系统.

预处理阶段  预处理器(cpp)根据以字符#开头的命令,修改原始的c程序.比如hello.c第一行的#include <stdio.h >命令告诉预处理器读取系统头文件stdio.h的内容,并把它直接插入程序文本中,结果就得到另外一个c程序,通常是以.i作为文件扩展名.

编译阶段,编译器(ccl )将文本文件hello.c 翻译成文本文件hello.s,它包含了一个汇编语言程序.汇编语言程序的每句语句都以一种标准的文本格式确切的描述了一条低级机器语言指令.汇编语言是非常有趣的,因为他为不同的高级语言的不同编译器提供了通用的输出语言,例如c编译器和fortran编译器产生的输出文件用的是一样的汇编语言.

汇编阶段, 接下来,汇编器(as )将hello.s翻译成机器语言指令,把这些指令打包成一种叫做 可重定位目标程序的格式,并将结果保存在目标文件hello.o.

hello.o是一个二进制文件,它的字节编码是机器语言指令而不是字符.如果我们在文本编辑器中打开hello.o文件,看到的将是一堆乱码.

链接阶段,请注意,hello程序调用printf函数,他是每个c编译器都会提供的标准c库的一个函数.printf函数存在一个名为printf.o的单独的编译好的目标文件中,而这个文件必须以某种方式合并到我们的hello.o程序中,链接器(ld)就负责处理这种合并,结果就得到hello文件,他是一个可执行目标企鹅文件 ,(或者简称为可执行文件),可以被加载到内存中,由系统执行.

旁注 GNU项目

gccgnu(gun's  not  unix )的缩写,是发起的一个免费的慈善项目(cs大法好,这种开源精神啊啊啊啊啊 ,一生推,)

1.3 了解编译器如何工作是大有益处的

对于像hello.c这样简单的程序,我们可以依靠编译系统生成正确有效的机器代码.但是 有一些主要的愿原因促使程序员必须知道编译器是如何工作的 其原因如下

优化程序性能 现代编译器都是成熟工具 通常可以生成很好的代码  作为程序员 我们无需为了写出高质量的代码而去了解编译器的内部工作  但是 为了在c 程序中做出好的编码选择 我们确实需要了解一些机器代码以及编译器将不同的c语句转化成机器代码的方式 .例如 一个switch语句是否比一系列的if then else语句高效的多

在第三章 我们将介绍两种相关的机器语言 IA32 X86-64.会介绍编译器如何把不同的c语言结构转化成他们的机器语言的   第五章 学习如何通过简单转换c语言代码 以帮助编译器更好的完成工作  从而调整c程序的性能. 第六章  学习存储器的层次结构特性 c语言编译器将数组存放在编译器的方式 以及c程序是如何能够利用这些知识从而更高效的运行

链接时出现的错误  根据我们的经验 一些最令人困扰的程序往往都与连接器操作有关.尤其当你准备构建大型的软件系统时  .例如 连接器 报告它无法解析一个引用 这是什么意思?在第七章  会得到解答

避免安全漏洞 多年来 缓冲区溢出

是造成大多数网络和Internet服务器安全问题的主要原因.存在这些错误是因为很少有人能理解限制他们从不收信任的站点接受数据的质量和格式的重要性.学习安全编程的第一步就是理解数据和控制信息存储在程序栈上的方式引起的后果 作为学习汇编语言的一部分 将在第三章描述栈原理和缓冲区溢出错误.还将学习程序员 编译器 和操作系统可以用来降低攻击威胁的方法

1.4  处理器读并理解存储在存储器中的指令

此刻 hello.c源程序已经被编译器系统翻译成可执行文件hello  并存放在磁盘上面.

要想在unix系统运行该可执行文件  我们将它的文件名输入到称为外壳的应用程序中

Unix>./hello

helloworld

Unix>

外壳是一个命令行解释器 它输出一个提示符 等待你输出一个命令行 然后执行这个命令.

如果该命令行的第一个单词不是一个内置的外壳命令  那么外壳就会假设这是一个可执行文件的名字   它将加载并运行这个文件   所以在此列中  外壳将加载并运行 hello程序 然后等待程序终止       hello程序在屏幕上输出他的信息 然后终止    外壳随后输出一个提示符 等待下一个输入的命令行   

1.4.1  系统的硬件组成

为了理解hello程序运行时  发生了什么  我们需要理解一个典型系统的硬件组织    

总线

贯穿整个系统的是一组电子管道 称作总线  它携带信息字节并负责在各个部件间传递   通常总线被设计成传递定长的字节快 也就是字  字中的字节数(即字长)就是一个基本的系统参数 在各个系统中的情况都不尽相同    现在大多数机器字长有的是4个字节 有的是8个字节   为了讨论方便 假设字节为四个字节 并且总线每次只能传送一个字

IO设备

这是系统与外部世界的联系通道   我们的事例系统包括

发布了30 篇原创文章 · 获赞 1 · 访问量 4760
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章