编译器
编译器就是将高级语言翻译成机器语言的一个工具。
Build
build过程或使用gcc编译时,可以分解为:
- 预处理
- 编译
- 汇编
- 链接
预编译
经过预编译后的.i文件不包含任何宏定义,因为所有的宏都已经被展开,并且包含的文件也已近被插入到.i文件中。
当我们无法判断宏定义是否正确或头文件包含是否正确时,可以查看预编译后的文件来确认。
gcc -E hello.c -o hello.i
或
cpp hello.c > hello.i
编译
编译过程就是把预处理完的文件进行一系列的词法分析、语法分析、语义分析以及优化后产生的相应地汇编代码文件。
(这个到后面学习编译原理的时候再看吧,之前在学校学的一点都快忘光了=.=)
gcc -S hello.i -o hello.s
汇编
汇编器是将汇编代码转变成机器可执行的指令,每一个汇编语句几乎都对应一条机器指令。
它根据汇编指令和机器指令的对照表,一一翻译。
gcc -c hello.s -o hello.o
或
as hello.s -o hello.o
直接从源代码文件开始,经过预编译、编译和汇编,直接输出目标文件:
gcc -c hello.c -o hllo.o
链接
模块拼装–静态链接:
链接的主要内容就是把各个模块之间相互引用的部分处理好,使得各个模块之间能够正确地衔接。
链接过程主要包括了:
- 地址和空间分配
- 符号决议
- 重定位
- …
每个模块的源代码文件经过编译器编译成目标文件,目标文件和库一起链接形成最终的可执行文件。
最常见的库是运行时库,它是支持程序运行的基本函数的集合。
库其实就是一组目标文件的包(也就是一些常用的代码编译成目标文件后打包存放)
重定位
重新计算各个目标的地址过程,每个要被修正的地方叫一个重定位入口