GCC编译步骤和过程分析(转载)

通常我们在编译时,会简单的使用一条命令,gcc hello.c -o hello,就会产生一个可执行文件,这样做无可厚非,原因在于gcc把哪些复杂的步骤都屏蔽了,只提供了一个很简单的使用命令。

其实在编译时,主要包含4个步骤,分别是

<1>预处理(preprocess)  gcc -E hello.c -o hello.i

<2>编译(compile)                 gcc -S hello.c -o hello.s

<3>汇编(assembly)             gcc -c hello.s -o hello.o

<4> 链接(link)                       ld  hello.o xx.o -o hello | gcc hello.o -o hello

下面分别就四个步骤做简要介绍

第一步:预处理

预处理主要是处理以#开头的部分,比如包含头文件,展开宏定义,条件预处理指令,处理规则如下:

a.  删除所有的define,并展开宏定义

b. 处理条件预处理执行.

c. 把头文件包含进来,注意这个过程是递归进行的,也就是头文件包含的头文件也会被包含进来。

d. 删除注释

e. 添加行号,便于后期调试

f. 保留pregma

第二步:编译

编译是将预处理产生的文件进行一系列的词法分析,语法分析,语义分析及优化后生成相应的汇编代码文件。

词法分析主要是使用基于有线状态机的scanner分析出Token

语法分析对有扫描器产生的Token进行语法分析,从而产生语法树木(采用上下文无关语法分析)

语义分析,编译器能分析的语义是静态语义,静态语义通常包括声明和类型的匹配,类型的转换比如当一个浮点型的表达式赋值给一个整型的表达式时,其中就隐含了一个浮点型到整型转换的额过程,语义分析过程需要完成这个步骤。比如讲一个浮点型赋值给一个指针的时候,语义分析程序就发现这个类型不匹配,编译器会报错。动态语义一般指在运行期出现的语义相关问题,比如讲0作为除数是一个运行期语义错误。

第三步:汇编

汇编是将编译产生的汇编代码文件转变成可执行的机器指令。这一步相对来说比较简单,每个汇编语句都有相对应的机器指令,只需根据汇编执行和机器指令的对照表一一翻译就可以了。

第四步:链接

虽然上一步产生的文件已经是机器指令文件,但是依然无法执行,原因在于某些符号无法解析,比如printf,所以需要链接,链接过程主要完成的是重定位,也就是符号解析,将符号对应的地址替换成正确的地址。例如printf可能会存在于printf.o文件中,在hello.o中,汇编时可以先将printf符号的地址设置为0,等到了链接这一步,在与printf.o链接,从而确定printf符号的位置。

预处理产生.i文件,编译产生汇编文件,汇编产生目标文件(机器指令),链接产生可执行文件。
--------------------- 
作者:sheldonwong 
来源:CSDN 
原文:https://blog.csdn.net/sheldonwong/article/details/75216545 
版权声明:本文为博主原创文章,转载请附上博文链接!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值