一、GCC编译过程

本文详细描述了GCC编译过程的五个主要步骤,包括词法分析、语法分析、语义分析、中间代码生成与优化以及代码生成和链接,同时介绍了预处理阶段的功能和链接阶段的动态与静态链接选项。
摘要由CSDN通过智能技术生成

编译过程

编译过程可大致分为以下五个步骤
(1)词法分析:将源文件流拆分为以Token表示的字符表,给语法分析程序使用
(2)语法分析:根据各个词法单元的第一个分量构造语法树
(3)语义分析:根据符号表和语法树检测源程序
(4)中间代码生成和优化:根据语义分析输出,生成机器语言的中间表示,如三地址码
(5)代码生成和优化:把中间表示形式映射到目标机器语言

GCC编译过程

hello.c的源码如下:

#include <stdio.h>
int main(){
        printf("hello,world!");
}

在编译时添加–save-temps,用于保存中间文件,添加–verbose用于查看详细工作流程

gcc hello.c -o hello --save-temps --verbose

请添加图片描述
可以看到GCC的编译主要包括四个阶段,即
预处理 Preprocess
编译 Compile
汇编 Assemble
链接 Link

该过程分别使用了cc1,as和collect2三个工具:
其中cc1是编译器,保证hello.c->hello.i->hello.s
之后由as汇编器将hello.s汇编为hello.o目标文件
最后由链接器将ld命令封装,将C语言运行库CRT中的目标文件以及动态链接库.so进行链接,使程序可执行

预处理阶段

gcc -E hello.c -o hello.i

请添加图片描述
…………
请添加图片描述

预处理阶段的主要功能有:

包含头文件:预编译器负责处理#include预处理指令,将指定的头文件内容复制到源代码文件中。

宏替换:预编译器处理#define预处理指令,将定义的宏在源代码中进行替换。

条件编译:预编译器处理#if,#ifdef,#ifndef,#else,#elif和#endif等预处理指令,根据指定的条件决定是否编译某部分代码。

删除注释:预编译器会移除源代码中的所有注释,使其不会出现在生成的目标代码中。

引用其他预处理指令:预编译器还可以处理如#error,#pragma等其他预处理指令。

编译阶段

gcc -S hello.i -o --masm=intel -fno-asynchronous-unwind-tables

GCC默认使用AT&T格式的汇编语言,编译时添加选项–masm=intel可以将其指定为intel模式,-fno-asynchronous-unwind-tables用于生成没有cfi宏的汇编指令,以提高可读性
在这里插入图片描述
编译阶段将经过预处理的代码转换为机器语言,通常为汇编语言

汇编阶段

gcc -c hello.s -o hello.o
file hello.o
objdump -sd hello.o -M intel

请添加图片描述
此时的目标文件hello.o是一个可重定位文件,可以使用objdump命令查看。
在其中可以发现,由于未进行链接,对象文件中符号的虚拟地址还未确定,字符串“hello”的地址被设定为了0x0000,作为参数传递字符串地址的rdi寄存器被设置为0x0,而call puts指令中puts()函数的地址被设置为下一条指令的地址0x18

链接阶段

gcc hello.o -o hello
objdump -sd hello -M intel

请添加图片描述

链接分为动态链接和静态链接,gcc默认动态链接,可加-static改为静态。
链接阶段主要包括地址和空间分配,符号绑定和重定位

  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值