1.1 hello程序
1.1.1 编译系统如何工作
#include <stdio.h>
int main() {
printf("hello,world\n");
return 0;
}
编写一个简单的hello.c
程序,输出hello,world
调用gcc
即可对代码进行编译,生成可执行文件hello
gcc hello.c -o hello
编译过程可以分为4个阶段:
- 预处理
pre-processer
- 编译
compiler
- 汇编
assembler
- 链接
linker
接下来逐个解释
- 预处理
预处理器会根据以#
开头的代码,来修改原始程序,例如hello
程序中引入头文件stdio.h
,预处理器会读取该头文件中的内容,将其中的内容直接插入到源程序中,结果就得到了另外一个c
程序,后缀为.i
,所以hello.c
经过预处理后得到hello.i
,仍旧是一个文本文件
- 编译
编译器会将hello.i
翻译成hello.s
,包括词法分析、语法分析、语义分析、中间代码生成以及优化等一系列操作,具体可参见《编译原理》
- 汇编
汇编器根据指令集将汇编程序hello.s
翻译成机器指令,并按照固定规则进行打包,得到可重定位目标文件hello.o
,是一个二进制文件,但是还不能执行
- 链接
程序中调用了printf
函数,其在printf.o
的文件中,这是一个提前编译好的目标文件,链接器负责把hello.o
和printf.o
进行合并,得到可执行文件hello
,此时hello
就可以被加载到内存中执行了
此时hello
已经存储在磁盘上,可以在终端中执行hello
./hello
hello,world
1.1.2 计算机系统硬件组成
CPU
中央处理单元(Central Processing Unit,CPU),也称处理器,CPU
里面有一个Program Count
,简称PC
,实质上是一个大小为一个字(word)的存储区域,里面存放某一条指令的地址,电脑一上电,就开始执行PC
指向的指令,然后更新PC
,使其指向下一条要执行的指令
- 32位机器,一个字是4个字节,也就是32位
1 word = 4 Byte
- 64位机器,一个字是8个字节,也就是64位
1 word = 8 Byte
寄存器文件
寄存器就是CPU
内部的一个存储设备,寄存器文件是由一些单字长(1 word)的寄存器构成,每个寄存器都有自己唯一的名字,可以理解为一个临时存放数据的空间
ALU
算术逻辑单元(Arithmatic Logic Unit),进行算术运算和逻辑运算
主存
也称为内存,处理器在处理数据时,主要存放程序指令及数据
- 从物理上讲,内存就是由一组动态随机存取存储器
DRAM
芯片组成- 从逻辑上讲,内存可以看成一个从零开始的大数组,每个字节
Byte
都有相应的地址
总线
贯穿整个系统的是一组电子管道,称作总线
内存和处理器之间通过总线来进行数据传递,通常总线被设计成传送固定字长的字节块,也就是字word
输入输出设备
例如键盘、鼠标、显示器以及磁盘等,每一个输入输出设备都通过一个控制器或者适配器与IO
总线相连