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

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

相关文章

安卓链接正常显示,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.

C++/《C/C++程序编译流程》

程序的基本流程如图:   1.预处理        预处理相当于根据预处理指令组装新的C/C++程序。经过预处理,会产生一个没有宏定义,没有条件编译指令,没有特殊符号的输出文件,这个文件的含义同原本的文件无异,只是内容上有所不同。 读取C/C++源程序,对其中的伪指令(以#开头的指令)进行处理将所有的“#define”删除,并且展开所有的宏定义处理所有的条件编译指令,如:“#if”、“

编译linux内核出现 arm-eabi-gcc: error: : No such file or directory

external/e2fsprogs/lib/ext2fs/tdb.c:673:29: warning: comparison between : In function 'max2165_set_params': -。。。。。。。。。。。。。。。。。。 。。。。。。。。。。。。。 。。。。。。。。 host asm: libdvm <= dalvik/vm/mterp/out/Inte

Vue2电商项目(二) Home模块的开发;(还需要补充js节流和防抖的回顾链接)

文章目录 一、Home模块拆分1. 三级联动组件TypeNav2. 其余组件 二、发送请求的准备工作1. axios的二次封装2. 统一管理接口API----跨域3. nprogress进度条 三、 vuex模块开发四、TypeNav三级联动组件开发1. 动态展示三级联动数据2. 三级联动 动态背景(1)、方式一:CSS样式(2)、方式二:JS 3. 控制二三级数据隐藏与显示--绑定styl

LabVIEW程序员是怎样成长为大佬

成为一名LabVIEW编程领域的“大佬”需要时间、实践、学习和解决复杂问题的经验。尽管LabVIEW作为一种图形化编程语言在初期可能相对容易上手,但要真正成为精通者,需要在多个层面上深入理解。以下是LabVIEW程序员如何逐步成长为“大佬”的路径: 1. 打好基础 LabVIEW的大佬们通常在初期会打下非常坚实的基础,理解LabVIEW编程的核心概念,包括: 数据流编程模型:Lab