程序员的自我修养-第二章 编译与链接

2024-06-03 02:44

本文主要是介绍程序员的自我修养-第二章 编译与链接,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

gcc hello.c ./a.out

编译分解成四步骤:

预处理,编译,汇编和链接

源码->.i文件->.s文件->.o文件

gcc -E hello.c -o hello.i (只进行预编译) --预处理器

通过查看.i文件可以看到宏展开后和头文件展开后的情况

gcc -S hello.i -o hello.s(进行编译,生成汇编代码)--编译器

gcc只是个封装,会根据不同参数调用 预编译编译程序cc1,汇编器as,链接器ld

gcc -c hello.s -o hello.o (将汇编转换成机器指令,即目标文件 Object File,也经常被称为模块) --汇编器

ld -static crtl.o crti.o crtbeginT.o hello.o --start-group -lgcc -lgcc_eh -lc-end-group crtend.o crtn.o(将相关.o链接起来形成一个可执行文件) --链接器

编译器做了什么?
 

一般可分成6步:扫描,语法分析,源代码优化,代码生成,目标代码优化

扫描器(lex)的功能:词法分析,将源代码分割解析成一系列记号,一般可以分成:关键字,标识符,字面量(包含数字、字符串等),和特殊符号(如加号,等号)及将标识符存放到符号表,数字字符串等常量放到文字表等,供后面的步骤使用

语法分析(语法分析器 yacc):对扫描器产生的记号进行语法分析,从而产生语法树(Syntax tree),整个分析过程采用了上下文无关语法。语法树就是以表达式为节点的树

在这个过程中要根据运算符号确定语法树,因此该阶段必须能够识别运算符是否合法,如缺少括号等就是在这个过程报错(参见图2-3 p44)

语义分析(语义分析器 ):语法分析只是完成了语法层面的分析,实际是否有意义并不知道,比如两个指针相乘,是没有意义的,但语法上是合法的。编译器所能分析的只是静态语义(编译期可以确定的语义,如声明和类型的匹配,类型的转换),与之对应的动态语义(运行期才能确定的语义,比如除0错误);语义分析后,整个语法树都被标识了类型(参见图2-4 p45),整棵语法树都被更新

中间语言生成(源码级优化器):由于直接在语法树上进行优化会比较困难,会将整个语法树转换成中间代码(中间代码有很多种类型,不同编译器不一样,比较常见的有:三地址码和P-代码)

基本的三地址码:z=x op y, op 代表各类操作,如加减乘除

为了符合三地址码的格式,所有操作都会符合三地址码的格式,实例参见p46

中间代码使得编译器被分为前端和后端,前端负责生成中间代码(与机器无关),后端负责将中间代码转换成目标机器代码

目标代码生成和优化(编译器后端,主要包含代码生成器和目标代码优化器,p47):

代码生成器将中间代码转换成目标机器代码

目标代码优化器将对目标代码进行优化,比如使用位移代替乘法运算,删除多余指令

最终运行时的绝对地址都要在最终链接的时候确定,编译器负责将源码文件编译成一个未链接的目标文件,最终由链接器将目标文件链接起来,形成可执行文件

重定位:重新计算各个目标地址的过程(编译时无法确认另外一个模块变量地址,链接时可以确定,将无法确认的地址(0x00)修改成确定的地址)

每个要被修正的地方叫做重定位入口(参考p53)

符号:使用一个名称来代表一个地址(比如 jmp foo,foo代表一个地址)

链接:通过模块间符号的引用将多个模块拼接在一起的过程称为链接

模块拼接-静态链接

链接过程主要包括:地址和空间分配,符号决议和重定位

符号决议别名(符号绑定,名称绑定,名称决议,地址绑定,指令绑定)静态链接更倾向于使用决议,动态链接更倾向于绑定

这篇关于程序员的自我修养-第二章 编译与链接的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1025809

相关文章

Java编译生成多个.class文件的原理和作用

《Java编译生成多个.class文件的原理和作用》作为一名经验丰富的开发者,在Java项目中执行编译后,可能会发现一个.java源文件有时会产生多个.class文件,从技术实现层面详细剖析这一现象... 目录一、内部类机制与.class文件生成成员内部类(常规内部类)局部内部类(方法内部类)匿名内部类二、

IDEA编译报错“java: 常量字符串过长”的原因及解决方法

《IDEA编译报错“java:常量字符串过长”的原因及解决方法》今天在开发过程中,由于尝试将一个文件的Base64字符串设置为常量,结果导致IDEA编译的时候出现了如下报错java:常量字符串过长,... 目录一、问题描述二、问题原因2.1 理论角度2.2 源码角度三、解决方案解决方案①:StringBui

使用Python快速实现链接转word文档

《使用Python快速实现链接转word文档》这篇文章主要为大家详细介绍了如何使用Python快速实现链接转word文档功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 演示代码展示from newspaper import Articlefrom docx import

解决IDEA使用springBoot创建项目,lombok标注实体类后编译无报错,但是运行时报错问题

《解决IDEA使用springBoot创建项目,lombok标注实体类后编译无报错,但是运行时报错问题》文章详细描述了在使用lombok的@Data注解标注实体类时遇到编译无误但运行时报错的问题,分析... 目录问题分析问题解决方案步骤一步骤二步骤三总结问题使用lombok注解@Data标注实体类,编译时

安卓链接正常显示,ios#符被转义%23导致链接访问404

原因分析: url中含有特殊字符 中文未编码 都有可能导致URL转换失败,所以需要对url编码处理  如下: guard let allowUrl = webUrl.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else {return} 后面发现当url中有#号时,会被误伤转义为%23,导致链接无法访问

maven 编译构建可以执行的jar包

💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」👈,「stormsha的知识库」👈持续学习,不断总结,共同进步,为了踏实,做好当下事儿~ 专栏导航 Python系列: Python面试题合集,剑指大厂Git系列: Git操作技巧GO

每日一练7:简写单词(含链接)

1.链接 简写单词_牛客题霸_牛客网 2.题目 3.代码1(错误经验) #include <iostream>#include <string>using namespace std;int main() {string s;string ret;int count = 0;while(cin >> s)for(auto a : s){if(count == 0){if( a <=

Windows环境利用VS2022编译 libvpx 源码教程

libvpx libvpx 是一个开源的视频编码库,由 WebM 项目开发和维护,专门用于 VP8 和 VP9 视频编码格式的编解码处理。它支持高质量的视频压缩,广泛应用于视频会议、在线教育、视频直播服务等多种场景中。libvpx 的特点包括跨平台兼容性、硬件加速支持以及灵活的接口设计,使其可以轻松集成到各种应用程序中。 libvpx 的安装和配置过程相对简单,用户可以从官方网站下载源代码

短链接算法原理

平时我们在上网的时候,印象最深刻的有一次是短链接的服务。例如:平时在微信上看一个网页的时候,如果我们选择在浏览器打开的时候,会看到很长的URL,我们分享的时候,会看到一个很短URL,这就是本次所说的短链接的应用之一。 长链接示例:https://mp.weixin.qq.com/s?__biz=MzAxNzMwOTQ0NA==&mid=2653355437&idx=1&sn=5901826ea63

Golang test编译使用

创建文件my_test.go package testsimport "testing"func TestMy(t *testing.T) {t.Log("TestMy")} 通常用法: $ go test -v -run TestMy my_test.go=== RUN TestMyTestMy: my_test.go:6: TestMy--- PASS: TestMy (0.