第二章 编译和链接
1. gcc hello.c
./a.out
预处理——编译——汇编——链接
2. 预处理:预编译 gcc –E hello.c –o hello.i或者hello.c >hello.i
源文件和头文件被预编译器cpp编译成.ii(c++) .i(c)文件,预编译处理规则:
[1] 将#define删除,展开所有宏定义
[2] 处理所有条件预编译指令,比如“#if”,“#ifndef”,“endif”,“else”
[3] 处理“#include”预编译指令,将包含的文件插入到预编译指令的位置
[4] 删除所有的注释“//”“/****/”
[5] 添加行号和文件名标识,比如#2“hello.c”2,便于编译时报错警告便以其产生条使用的行号信息
[6] 保留所有的#pragma编译器指令
3. 编译:gcc –S hello.i -o hello.s
编译就是把预处理完的文件进行一系列的词法分析、语法分析、语义分析及优化后生产相应的汇编代码文件。预编译和编译合并成一个cc1的程序
4. 汇编ashello.s –o hello.o或者gcc –c hello.s –o hello.o
将汇编代码转变成及其可移植性的指令。
直接从源文件开始经过预编译、编译和汇编生成目标文件:gcc -c hello.c –o hello.o
5. 链接
一个生成的可执行文件包含很多目标.o文件。包括地址和空间分配、符号决议(地址绑定)和重定位等步骤。就是把目标文件和库函数链接起来,最常见的库是runtime library即运行时库。
6. 编译器的工作
[1] 词法分析:扫描程序,产生一些记号:关键字、标示符、字面量和特殊符号
[2] 语法分析:将扫描器产生的记号生成以表达式为节点的语法树
[3] 语义分析:主要是静态语义,包括生命和类型的匹配,转换。经过语义分析,语法树的表达式被标识了类型,(有的要隐式转换)
7. 中间语言生成
源码级优化器,产生中间代码,代码生成器把中间代码转换成目标机器代码,目标代码优化器对目标代码优化、选择合适的寻址方式等
第三章 目标文件
8.
[1] 代码段:代码、函数被放在数代码段.text或者.code
[2] 数据段:已初始化局部静态变量和全局变量被放在数据段.data
[3] 未初始化的全局和局部静态变量默认为0,放在.bss中,因为为0所以在.data中分配空间没有必要。
[4] 只读数据段:.rodata就是只读变量const和字符串常量。
[5]
9. 目标文件包括一个文件头、描述了文件属性,如是否可执行、动态还是静态、入口地址、等,文件头包括一个段表,记录了各个段在文件中的偏移和短的属性。