编译的整个过程:预编译、编译、汇编、链接


预处理, 展开头文件/宏替换/去掉注释/条件编译 (test.i main .i)
编译, 检查语法,生成汇编 ( test.s main .s)
汇编, 汇编代码转换机器码 (test.o main.o)
链接 链接到一起生成可执行程序 a.out
在这里插入图片描述

1.预处理阶段 gcc -E main.c -o main.i ,然后生成.i文件

预编译过程主要做4件事:
①展开头文件
在写有#include 或#include "filename"的文件中,将文件filename展开,通俗来说就是将fiename文件中的代码写入到当前文件中;
②宏替换
③去掉注释,添加行号和文本标识
④条件编译
即对#ifndef #define #endif进行判断检查,也正是在这一步,#ifndef #define #endif的作用体现出来,即防止头文件被多次重复引用

2.编译

1.词法分析:扫描器来进行;
(1)词:关键字,标识符,字面量(数字,字符串),特殊符号(加号,等号)

(2)将标识符放到符号表

(3)将数字,字符串放到符号表

2.语法分析:语法分析器,语法树

3.语义分析:语义分析器

(1)分析静态语义(即编译时期可以确定的语义):声明和类型匹配,类型转换

(2)分析动态语义(即运行时才能确定的语义)

(3)对符号表中的符号进行更新。
4.代码优化 ,生成汇编代码文件:代码生成器,目标代码优化器

将代码转成汇编代码,并且在这个步骤中做了两件很重要的工作:
①编译器在每个文件中保存一个函数地址符表,该表中存储着当前文件内包含的各个函数的地址;
②因为这步要生成汇编代码,即一条一条的指令,而调用函数的代码会被编译成一条call指令,call指令后面跟的是jmp指令的汇编代码地址,而jmp指令后面跟的才是“被调用的函数编译成汇编代码后的第一条指令”的地址,但是给call指令后面补充上地址的工作是在链接的时候做的事情。

3.汇编

汇编命令:gcc -C main.s -o main.o,然后生成.o文件,即可重定位(重入)的二进制文件

将汇编代码转成机器码
1.将汇编指令翻译成二进制
2.生成符号表
在这里插入图片描述
3.生成各种段”Segme”
在这里插入图片描述
(0)ELF header文件头:描述整个文件的文件属性:是否可执行,静态链接还是动态链接级入口地址,目标硬件,目标 操作

(1).text代码段:存放源代码编译后的机器指令。普通局部变量也当做指令
(2).data数据段:存放已初始化的全局变量和局部静态变量

(3)相当于没有的.bss段:,不占据空间,只是下面两种变量的预留位置

记录未初始化的全局变量和局部静态变量的大小总和。(这两种变量默认为0本可以放在.data段,但是没必要,浪费空间。所以就有.bss段,他的存在节省了磁盘空间。.bss段在文件中不占据空间,只是预留位置。)

(4).comment注释信息段。

4.链接

链接命令:gcc mian.o –o mian ,生成ELF文件(即可执行文件),有头和.data、.text段等
编译器将生产的多个.o文件链接到一起生成一个可执行.exe文件;
但是在这个过程中,编译器做的一个重要的事情是将每个文件中call指令后面的地址补充上;方式是从当前文件的函数地址符表中开始找,如果没有,继续向别的文件的函数地址符表中找,找到后填补在call指令后面,如果找不到,则链接失败。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值