目录
1. 程序的翻译环境和运行环境
.c 文件是源文件或者源程序
但是在电脑中运行的文件都是 .exe 可执行文件
所以 .c的源文件需要经过 编译+链接 变成 .exe可执行文件
.c 文本文件------翻译环境------->.exe二进制文件------运行环境------->输出
2. 程序编译、链接过程
编译:需要编译器
链接:需要链接器
每一个源文件经过编译器都会生成一个目标文件
3. 翻译环境
3.1 编译过程
3.1.1 预编译(预处理)
预处理阶段:文本操作-----> 将.c 文件变成 .i 文件
- 头文件的包含:拷贝头文件
- 删除注释: 使用空格代替注释(包括头文件中的注释)
- #define 定义的替换
3.1.2 编译
编译阶段:将C语言代码翻译成汇编代码------->将.i 文件变成 .s 文件
- 语法分析:检查C语言代码有没有错误
- 词法分析:将C代码进行拆解,比如哪些是符号,哪些是操作符等等
- 语义分析:读懂语义,才能将C代码翻译成汇编
- 符号汇总:将全局变量、函数名等符号,进行汇总,为链接做准备
3.1.3 汇编
汇编阶段:将汇编文件翻译成二进制文件------->将.s 文件变成 .obj 文件
- 形成符号表:
每个源文件都会生成对应的目标文件
编译阶段将全局变量、函数名等符号,进行汇总
而汇编将编译阶段汇总的符号生成一个符号表,就是将符号和地址对应起来,生成一个类似表格一样的结构
这里:
- Add 0x000的地址是没有用的,但是main程序的文件中包含它,那就要生成一个地址,现在还没将具体的地址链接起来,所以这个地址是无效的
- 对应的add.c 中有个函数,会生成符号表,例如 Add 0x100
- main函数也会形成符号表
- 只有函数名、全局变量等才会在编译阶段进行符号汇总,然后汇编阶段形成符号表
3.2 链接过程
将多个目标文件经过链接器链接,生成可执行程序.exe
3.2.1 合并段表
.obj 目标文件有自己的固定格式(elf文件格式),都被分成了几个段
将不同的目标文件链接在一起
这样,对应段上的数据就会放到一起去了
不管有多个.obj目标文件,最后只能生成一个.exe可执行程序
3.1.2 符号表的合并和重定位
这时候,需要进行符号表的合并和重定位
我们知道main函数里面那个Add的地址是错误的,且Add是有重名的
所以将两个Add合并,取有效的Add地址,这里是 0x 100,相当于符号表的重定位
main函数没有冲突,直接生成符号表
这样函数名和地址对应起来,需要的时候直接去地址中找就行了
- 如果Add的代码没有了
- 那么合并符号表的时候,就会找不到Add的地址,就会报错
- 所以报错是链接错误、而符号表的合并就是在链接期间完成的
- 因为main函数文件那个Add只是声明函数,之前函数章节介绍过,声明是告诉这里可能有个函数长啥样,但是具体有没有无所谓
例子:形成符号表
4. 运行环境