[转]GCC编译过程分解

GCC编译过程分解 – 原地址

以helloworld为例分析gcc编译过程:

#include <stdio.h>
int main()
{
         printf(“Hello World\n”);
         return 0;
}

通常我们使用gcc来生成可执行程序,命令为:gcc hello.c,生成可执行文件a.out
实际上gcc hello.c可以分解为4个步骤,分别是预处理(Preprocess),编译(Compilation),汇编(Assembly)和链接(Linking),如下图所示:

预编译

gcc –E hello.c –o hello.i,以下为预处理后的输出文件hello.i的内容

# 1 "hello.c" 
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "hello.c"
# 1 "/usr/include/stdio.h" 1 3 4
# 28 "/usr/include/stdio.h" 3 4

/ 省略了部分内容,包括stdio.h中的一些声明及定义 /

# 2 "hello.c" 2
int main()
{
 printf("Hello World\n");
 return 0;
}

预编译过程主要处理那些源代码中以#开始的预编译指令,主要处理规则如下:

  • 将所有的#define删除,并且展开所有的宏定义;
  • 处理所有条件编译指令,如#if,#ifdef等;
  • 处理#include预编译指令,将被包含的文件插入到该预编译指令的位置。该过程递归进行,及被包含的文件可能还包含其他文件。
  • 删除所有的注释//和 /**/;
  • 添加行号和文件标识,如#2 “hello.c” 2,以便于编译时编译器产生调试用的行号信息及用于编译时产生编译错误或警告时能够显示行号信息;
  • 保留所有的#pragma编译器指令,因为编译器须要使用它们;

编译

编译过程就是把预处理完的文件进行一系列词法分析,语法分析,语义分析及优化后生成相应的汇编代码文件。gcc –S hello.i –o hello.s,以下为编译后的输出文件hello.s的内容

         .file  "hello.c"
         .section    .rodata
.LC0:
         .string      "Hello World"
         .text
.globl main
         .type         main, @function
main:
         pushl         %ebp
         movl          %esp, %ebp
         andl $-16, %esp
         subl  $16, %esp
         movl          $.LC0, (%esp)
         call   puts
         movl          $0, %eax
         leave
         ret
         .size main, .-main
         .ident        "GCC: (GNU) 4.4.0 20090506 (Red Hat 4.4.0-4)"
         .section    .note.GNU-stack,"",@progbits

汇编

汇编器是将汇编代码转变成机器可以执行的命令,每一个汇编语句几乎都对应一条机器指令。汇编相对于编译过程比较简单,根据汇编指令和机器指令的对照表一一翻译即可。
gcc –c hello.c –o hello.o,由于hello.o的内容为机器码,不能以文本形式方便的呈现。

链接

链接器ld将各个目标文件组装在一起,解决符号依赖,库依赖关系,并生成可执行文件。
ld –static crt1.o crti.o crtbeginT.o hello.o –start-group –lgcc –lgcc_eh –lc-end-group crtend.o crtn.o (省略了文件的路径名)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值