编译过程

一、词法分析

将源代码通过扫描器转换为记号

二、语法分析

将记号进行语法分析得到语法树(不能理解这个语句是否真的有意义)

三、语义分析

用语义分析器分析语义,只能分析静态语句

四、中间语言生成

通过源码级优化器优化掉编译期可以确定的值,得到中间代码(通常得到三地址码格式x=y op z)

五、目标代码生成和优化

通过代码生成器和目标代码优化器将中间代码转换为目标机器代码,然后通过优化器优化

到这一步,目标代码如果有变量定义在其他文件之中,其绝对地址都是在最终连接的时候才能确定的。

因为在很久之前,每次当代码改变的时候,程序员都要计算跳转指令的地址,非常容易出错,所以出现了重定位(Relocation),发明了汇编语言之后用符号(Symbol)来表示一个地址。

链接(Linking)的定义:人们把每个源代码模块独立的编译,然后按照要求将他们组装起来,这个组装的过程就是链接。链接的过程包括地址和空间分配(Address and Storage Allocation)、符号决议(Symbol Resolution)和重定位(Relocation)等步骤 。

重定位:比如在A文件有个var变量,我在B文件中要给他赋值,在文件编译的时候,编译器不知道var的目标地址,所以把赋值的目标地址设置为0,等待链接器链接,然后A和B链接的时候,链接器填写var的地址,这个填写的过程被称为重定位。

一个.c文件经过编译器成为目标文件.o,中间目标文件和库一起链接形成最终可执行文件,最常见的库就是运行时库。

动态链接库(.dll .so)和静态链接库(.lib .a) 可以通过file name 命令来查看文件格式

目标文件中

段表存在于头文件之中

汇编之后的机器指令存在代码段中(.text)和(.code)

全局变量和局部静态数据存在数据段(.data)

没有初始化的变量放在.bss段中(.bss只是为未初始化的变量预留位置)

分开数据段和代码段的原因是:
可以分别设置两个段的可读和可写性能,用于防止程序被有意无意的修改。
指令区和数据区的分离可以提高程序的局部性,提高缓存命中率
当程序中运行多个该程序的副本的时候,指令部分只需要保存一份就可以了,可以节省大量内存
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值