《深入理解计算机系统》 第一章 计算机系统漫游 : 从helloworl初识程序在计算机中的存储,编译和运行
一 : 程序如何在计算机中表示,存储?
1.1 C语言的helloworld程序 hello.c ,内容大致如下
#include <stdio.h>
main() {
printf("hello world\n");
}
1.2 计算机眼中的 hello.c ,大部分现代计算机都使用ASCII标准来翻译文本内容
1.3 信息就是位 加 上下文
从上图中可以看到,在计算机眼中,每个字母和数字,包括换行符等特殊符号都翻译成了一个唯一的数字,而这个数字在计算机中是使用一个字节大小的空间,即8个bit来表示的。
hello.c 的表示方法说明了一个基本的思想 :系统中所有的信息包括 磁盘文件,内存中的程序,包括网上的用户数据,以及正在网络传输的内容其本质 都是由遗传比特表示。
1.3.1 文本文件 :在计算机程序中,使用ASCII标准的字符构成的文件成为 文本文件,例如hello.c ,使用对象是人。
1.3.2 二进制文件 :可以理解为由ASCII标准翻译的一系列唯一的单字节大小的数值构成的文件,使用对象是电脑。
1.3.3 上下文 :即使相同的 字节码序列 在不同的上下文中 也可能表示不同的含义,在不同的上下文中,一个同样的字节码序列可能表示 整数,浮点数,字符串 或者 机器指令,作为程序员我们需要了解数字的机器表示方式,因为它与实际的整数 和实数是不同的,它是对真值的有限近似值,有时候会有意向不到的行为表现 ,例如计算机中 两个正数 相加 可能得到负数。 这方面的基本原理将在后续详细描述。
二 : 程序如何在计算机中编译?
2.1 hello.c 的 从人读懂的文本 到 机器可执行的 文件,这个过程 我们称之为 :编译
2.1.1 预处理阶段 :这一阶段预处理器 cpp 会修改原来的c程序文本内容,比如hello.c的第一行 #include<stdio.h> 就是告知预处理器读取系统头文件stdio.h的内容,并插入到程序文本中,这样我们就得到了一个新的C程序,程序扩展名以 i 结尾。
2.1.2 编译阶段 :此阶段完成会得到一个 汇编语言文本文件hello.s,如下图
2.1.3 汇编阶段 :此阶段 是将 汇编语言翻译成 机器指令,也就是说我们会得到一个 hello.o 的二进制文件,它包含的17个字节是函数main的指令编码,如果在文本编辑器中打开 将是乱码,在 此阶段前,hello.c / hello.i / hello.s 都是文本编辑器可查看的,都是人可读的,而hello.o在文本编辑器中打开将是一堆乱码。
2.1.3 链接阶段:此阶段可以理解为 对二进制文件 需要调用的函数的 字节码文件 进行合并到 hello.o二进制文件中,例如我们需要打印除helloworld字符串,就需要调用C语言函数库中的printf函数,那么在本阶段,系统会将一个单独存放的编译好的printf.o文件内容并入到hello.o中,最后得到的hello文件就是一个可执行文件,连接器ld就是这个作用,那么就可以被加载到内存中并等待执行。
三 : 初探计算机如何运行程序?
3.1 识别启动命令 :当我们在键盘上输入 ./hello后,shell程序将字符逐一读入cpu中的寄存器,并把它门加载到内存。
3.2 将编译阶段产生的可执行文件加载到内存 :当我们输入完./hello后并按下 enter键,那么shell程序会识别到指令已经完成,那么它变开始通过一系列指令将hello可执行文件加载到内存中。
3.3 开始执行内存中的机器指令 :处理器开始执行main函数中的机器指令,并将 "hello,world\n" 从内存中复制到寄存器中,再从寄存器复制到显示设备,并最终展示。