计算机系统由硬件和软件组成!
跟随最简单的 hello,world 程序开始,了解系统执行hello程序时系统发生了什么,以及为什么会这样。
#include<stdio.h>
int main()
{
printf("hello,world");
return 0;
}
1、信息就是位+上下文
hello 程序的生命周期是从一个源程序(源文件)开始的,程序员使用代码编辑器编辑一个hello.c的文件。源程序实际上是一个由0和1组成的位(比特)序列,8个位组成一个字节,每个字节代表程序中的某些文本字符。大部分的现代计算机系统都使用ASCII标准来表示文本字符。
系统中所有的信息都是由一串比特表示的。区分不同数据对象的唯一方法就是我们读到这些数据对象时的上下文。
2、程序被其他程序翻译为不同的格式
hello 程序的生命周期是从一个高级C语言开始的,因为这种形式能够被人读懂,然而为了能在系统上运行hello.c程序,每条C语言语句都必须被其他程序转化为一系列低级机器语言指令,然后这些指令按照一种称为可执行目标程序的格式打包好,并且以二进制磁盘文件形式放起来。
在linux系统上,从源文件到目标文件的转化是由GCC编译器完成的。GCC编译器读取源文件,并把它翻译为一个可执行目标文件hello,这个翻译过程由四步组成。

- 预处理阶段:预处理器(cpp)根据字符 # 开头的命令,修改原始的C文件。比如 #include<stdio.h> 命令告诉预处理器读取系统头文件stdio.h的内容,并把它直接插入程序中,结果就得到了另一个C文件,通常是以 .i 结尾的文件名。
- 编译阶段:编译器(ccl)将文本文件hello.i 翻译成文本文件hello.s,它包含一个汇编语言程序,该程序包含main的定义,如下所示,每一条语句都以一种文本格式描述了一条低级机器语言指令。汇编语言是非常有用的,因为它为不同的高级语言的不同编译器提供了通用的输出语句。
main:
subq $8,%rsp
movl $.LCO,%edi
call puts
movl %O,%eax
addq $8,%rsp
ret
- 汇编阶段:接下来,汇编器(as)将hello.s 翻译成机器语言指令,把这些指令打包成一种叫做可重定位目标程序的格式,并将结果保存在目标文件hello.o中。hello.o 是一个二进制文件,它包含的17个字节是函数main的指令编码,如果我们以文本编辑器打开hello.o 文件,将会看到一堆乱码。
- 链接阶段:请注意,hello 程序中调用了printf 函数,它是每个C语言标准库都提供的标准C库中的一个函数。printf函数存在于一个名为printf.o 的单独的预编译好了的目标文件中,而这个文件必须以某种方式合并到我们的hello程序中,链接器(ld)就负责处理这种合并,结果得到hello文件,它是一个可执行文件,可以被加载到内存中,由系统执行。
3、了解编译系统如何工作是大有益处的
对于像hello这样简单的程序,我们可以依靠编译系统生成正确又有效的机器代码,但是,有一些重要的原因,促使程序员必须知道编译系统是如何工作的。
- 优化程序性能:现代编译器都是成熟的工具,通常可以生成很好的代码。但是为了在C程序中做出最好的编码选择,我们确实需要了解一些机器代码以及编译器将不同的C语言语句转化为机器代码的方式。比如,一个函数的调用开销有多大?一个switch 语句是否总是必一系列的if-else语句高效?等等问题。
- 理解链接时出现的错误:一些最令人困扰的程序错误往往都与链接器操作有关,尤其是构建大型的软件系统时。比如,链接器报告说它无法解析一个引用,这是什么意思?静态变量和全局变量的区别是什么?静态库和动态库的区别是什么?最重要的是,为什么有些链接错误直到运行时才会出现?
- 避免安全漏洞:多年来,缓冲区溢出错误是造成大多数网络和internet服务器上安全漏洞的主要原因。存在这些错误是因为很少有程序员能够理解需要限制从不受信任的源接受数据的数量和格式。学习安全编程的第一步就是理解数据和控制信息存储在程序栈上的方式会引起的后果。
4、处理器读并解释存储在内存上的指令
此刻,hello.c 程序已经被编译系统翻译为可执行文件hello,并被存储在磁盘上。在想在linux 上运行该程序,我们将它的文件名输入到名为shell 的应用程序上:
linux> ./hello
hello,world
linux>
shell是一个命令解释行,它输出一个提示符,等待一个命令输入,然后执行这个命令。如果该命名行的第一个单词不是内置的shell命令,那么shell就是假设这是一个可执行文件的名字,它将加载并运行这个文件。所以在此例中,shell 加载hello程序到内存中,然后运行该程序,屏幕上输出hello,world,然后程序结束,shell 继续等待下一个命令的输入。
Comments NOTHING