1、编译型语言和解释型语言
编译型语言,在程序执行之前,有一个单独的编译过程,将程序翻译成机器语言,以后执行这个程序的时候,就不用再进行翻译了,典型的如:C/C++
解释型语言,是在运行的时候将程序翻译成机器语言,所以运行速度相对于编译型语言要慢,如:java,C#,脚本语言
虽然Java程序在运行之前也有一个编译过程,但是并不是将程序编译成机器语言,而是将它编译成字节码(可以理解为一个中间语言)。
在运行的时候,由JVM将字节码再翻译成机器语言。
2、编译型语言的编译链接过程
从.cpp文件到.exe文件,一共经历了四个阶段
预编译、编译、汇编、链接
- 预编译
将.c/cpp文件编译成.i文件
删除注释
处理以#开头的预编译指令
添加行号和文件标识 - 编译
.i文件编译成.s文件
把预处理完的文件进行一系列词法分析、语法分析、语义分析及优化后 生产相应的汇编文件;
代码的优化
汇总所有的符号 - 汇编
.s文件生成.o文件
汇编器是将汇编代码转换成机器可以执行的指令,每一个汇编语句几乎都对应一条机器指令
汇编完成以后生成二进制可重定位目标文件(.obj) - 链接
合并所有obj文件的段,并调整段偏移和段长度,合并符号表,进行符号解析,给符号分配内存地址;
链接的核心:符号的重定位
那么在汇编完成后的.obj文件是什么格式?为什么不能运行呢?链接阶段的符号重定位又是什么鬼?
下面就来揭晓:
1.obj文件格式
以这个代码为例说明:
命令readelf -h main.o可以查看main.o文件的ELF文件头
可以看出mian.o文件中的入口地址为0x0,所以它是不可能运行的,还记得虚拟内存空间的分配吗(前128M不可访问,入口地址为0x08048000才
是正确地址),ELF Header的大小为52字节,十六进制为0x34
用objdump -h main.o查看.obj的内存格式
从上面可以看到.bss段和.comment段的入口地址是一样的,bss(better save space)节省的是文件的空间,而不是虚拟地址空间
obj文件格式如下:
既然.bss文件不保存,
用objdump -S main.o查看
用objdump -t main.o查看各个变量所在段的具体位置如下: