一、编译过程:主要是分为预编译阶段生成.i文件,编译阶段生成.asm文件,汇编阶段生成.obj文件,也就是一个可重定向的二进制目标文件。
1. 预编译:在这个阶段主要做一些代码文本的替换工作:
替换宏
解决所有的带有#的预编译命令
删除注释、添加行号和文件标识符、保留所有的带有#pragma编译器指令
指令:gcc -E test.c -o test.i
2.编译:在这个阶段主要是对预编译之后的文件进行 词法分析、语法分析(单条语句)、语义分析和代码优化,最后生成汇编代码, 指令:gcc -S test.i -o test.s
3.汇编:在汇编阶段主要是把汇编代码转换成一一对应的机器码,指令:gcc -c test.s -o test.o
那么此时.obj文件组成是怎样的呢?
那么我们所生成的.exe文件的组成和obj有何不同呢?
由以上两个图可知,他们之间的不同是多了一个program header。
二、链接过程
链接过程主要是分为两步:
第一步,链接器器首先把多个段进行合并,建立映射关系并且合并符号表,符号表进行符号解析(符号解析是让所有符号的引用 找到这个符号的所定义的地方。
符号解析完成后是给符号分配虚拟地址
第二步,进行符号重定向,把符号分配号的虚拟地址与符号表中定义的符号一一对应起来,让代码的指令可以根据符号的地址执行相应的操作。最后链接器会生成一个可执行文件。
三、运行
建立虚拟地址空间和物理内存的映射(创建映射结构体pcb,创建页目录,页表)
加载指令和数据
入口地址写入下一行指令寄存器
四、代码演示和objdump命令查看
#include <stdio.h>
int main()
{
int a;
int b;
a = 1;
b = 2;
printf("%d\n",a+b);
return 0;
}
readelf -h test.o
通过该命令查看到.o文件的文件头所有信息,包括地址记录,size记录什么的。
readelf -S test.o
通过该命令可查看到section headers中的内容,包括段内容、偏移量、属性等等。
objdump -d test.o
通过该命令可查看反汇编结果
objdump -S test.o
得到汇编后的机器码文件
objdump -t test.o
查看符号表
objdump -h test.o 查看.o文件的各个段(常用的段.data/.text/.bss/.comment)