程序的编译链接过程详解
首先我们简单了解一下内存布局:
程序的编译分为:
1.预处理:主要处理源代码文件中的以“#”开始的预编译指令(经过预编译后的.i文件不包含任何宏定义,因为所有的宏已经被展开,并且包含的文件也已经被插入到.i文件中)
2.编译:将预处理完的文件进行一系列词法分析,语法分析,语义分析以及优化后产生相应的汇编代码文件(生成.s文件)
3.汇编:汇编器将汇编代码转变成机器可以执行的指令,每一个汇编语句几乎对应一条机器指令(生成.o/.obj文件)
.o/.obj文件的组成格式
可执行文件的组成格式:
注:可执行文件比.obj文件多一个program head----有两个非常重要的load项,这两个项是按页面对齐(是将可执行文件中的某些段分配在一个页面上)
虚拟地址空间开辟内存的方式(mmap--磁盘往虚拟地址空间映射上用)
******虚拟内存的大小与CPU位数(不是地址总线)有关(CPU在ALU内运算)
16位CPU 地址总线 20 数据总线 16
8位CPU 地址总线 16 数据总线 8
链接:
按属性合并段(组织在一个页面上)
调整起始偏移量
合并符号表(让符号引用找到符号定义)
符号解析----分配内存地址
重定位:代码指令的编译是在编译过程中进行的,但编译过程中并不给分配地址,在指令中,所有函数指令和数据指令为0地址或者-4,因此,分配地址后要在代码段里将那些没有填写符号的正确的地址替换为正确地址(数据符号替换为符号的绝对地址,函数符号替换为和下一行地址的偏移量)
./a.out(执行可执行文件)
1.创建虚拟地址空间到物理内存的映射(创建内核地址映射结构体)创建页目录和页表
2.加载代码段和数据段
3.把可执行文件的入口地址写到CPU的PC寄存器当中