GCC编译过程

文章详细阐述了GCC在Ubuntu18.04环境下将C源码文件(如Helloworld.c)编译成可执行文件(如Helloworld.exe)的过程,包括预处理(.c->.i)、编译(.i->.s)、汇编(.s->.o)和链接(.o->.exe)四个阶段。预处理涉及处理#include、宏定义和条件编译指令;编译阶段将C代码转换为汇编代码;汇编阶段生成可重定位的.o对象文件;链接阶段完成地址分配和符号绑定,形成最终的可执行文件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

二进制文件

​ 计算机文件基本上分为两种:二进制文件和ASCII(也称纯文本文件),图形文件及文字处理程序等计算机程序都属于二进制文件.

​ 可重定位文件:ELF格式的二进制文件(可重定位即可以重新定位内存地址信息)

GCC编译过程(在ubntu18.04环境下完成)

​ 说一下GCC具体的过程(文件是如何变化又经历了什么)

Hello world.c文件——>Hello world.i文件——>Hello world.s文件——>Hello world.o对象文件——>Hello world.exe可执行文件

注:.c文件可以直接转化为.s和.o文件和.exe文件
例如将.c文件直接转化为.s文件所需要的指令为

gcc -S 'Hello world.c' -o 'Hello world.s'

依次经历的事件为:

首先给出一个C语言程序文件
在这里插入图片描述

  • 预处理 从.c文件转变为.i文件

在这里插入图片描述

打开‘Hello world.i’文件(一下为部分截取代码)

# 1 "Hello world.c"
#1 "<built -in>"
#1 "<command-line>"
...
extern int printf(const char *_restrict_format,...);
...
int main()
{
  printf("Hello world");
  return 0;
}

通过观察我们可以得知预处理的一些处理规则;

  • 递归处理”#include“ 预处理指令,将对应文件的内容复制到该指令的位置

  • 删除所有“#define”指令,并且在其被引用的位置递归地展开所有的宏定义

  • 处理所有条件预处理指令:“#if”、“#ifdef”、“#elif”、“#else”、“#endif”等

  • 删除所有注释

  • 添加行号和文件名标识

  • 编译阶段 从.i文件转变为.s文件

在这里插入图片描述

GCC默认使用AT&T格式(大部分Linux内核都是)的汇编语言,添加编译选项“-masm=intel”可以将其指定为我们熟悉的intel格式。编译选项"-fno-asynchrnous-unwind-tables"则用于生成没有cfi宏的汇编指令,以提高可读性。

在这里插入图片描述

打开文件所见内容

值得一提的是,生成的汇编代码中函数printf()被替换成了puts(),这是因为当printf()只有一个参数时,与puts()是十分类似的,与是GCC的优化策略就将其替换以提高性能

  • 汇编阶段 从.s文件转变为.o对象文件

在这里插入图片描述

​ 此时的目标文件’Hello world.o’是一个可重定位文件(Relocatable file),可以使用objdump命令(liunx自带命令不需要安装)来查看其内容

在这里插入图片描述

​ 此时由于还未进行链接,对象文件中符号的虚拟地址无法确定,于是我们看到字符串hello world的地址被设置为0x0000。

  • 链接阶段 将.o文件转变为.exe可执行文件

可分为静态链接和动态链接。GCC链接默认成为动态链接,这一阶段将目标文件及其依赖库进行链接,生成可执行文件,主要包括地址和空间分配、符号绑定和重定位等操作。

在这里插入图片描述

链接操作由链接器(ld.so)完成,结果就得到了hello文件,这是一个静态链接的可执行文件(加了编译选项-static)

同样file 文件 objdump命令 - sd +文件名 -M intel 执行

因为可执行文件含有大量的库文件,没有截取到相应的结果

理论上的结果应该是

call …<链接> 此链接(实际的符号地址)对应一段汇编代码,程序也就可以被加载到内存了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值