C++编译链接

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查看各个变量所在段的具体位置如下:
这里写图片描述