编译原理之美
宫文学
北京原点代码 CEO
46197 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 45 讲
开篇词 (1讲)
编译原理 · 期中考试周 (1讲)
编译原理之美
15
15
1.0x
00:00/00:00
登录|注册

23 | 生成汇编代码(二):把脚本编译成可执行文件

思考面向对象编程的实现
思考其他运算和语法的实现
一课一思
后端工作的实质
加深对编译过程的理解
二进制文件格式
链接过程
修改生成的汇编代码
遵守调用约定
优化过程
机械地翻译
课程小结
理解可执行文件
通过C语言调用playscript模块
从AST生成汇编代码
生成汇编代码

该思维导图由 AI 生成,仅供参考

学完两节课之后,对于后端编译过程,你可能还会产生一些疑问,比如:
1. 大致知道汇编程序怎么写,却不知道如何从 AST 生成汇编代码,中间有什么挑战。
2. 编译成汇编代码之后需要做什么,才能生成可执行文件。
本节课,我会带你真正动手,基于 AST 把 playscript 翻译成正确的汇编代码,并将汇编代码编译成可执行程序。
通过这样一个过程,可以实现从编译器前端到后端的完整贯通,帮你对编译器后端工作建立比较清晰的认识。这样一来,你在日常工作中进行大型项目的编译管理的时候,或者需要重用别人的类库的时候,思路会更加清晰。

从 playscript 生成汇编代码

先来看看如何从 playscript 生成汇编代码。
我会带你把 playscript 的几个有代表性的功能,而不是全部的功能翻译成汇编代码,一来工作量少一些,二来方便做代码优化。这几个有代表性的功能如下:
1. 支持函数调用和传参(这个功能可以回顾加餐)。
2. 支持整数的加法运算(在这个过程中要充分利用寄存器提高性能)。
3. 支持变量声明和初始化。
具体来说,要能够把下面的示例程序正确生成汇编代码:
//asm.play
int fun1(int x1, int x2, int x3, int x4, int x5, int x6, int x7, int x8){
int c = 10;
return x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + c;
}
println("fun1:" + fun1(1,2,3,4,5,6,7,8));
在加餐中,我提供了一段手写的汇编代码,功能等价于这段 playscript 代码,并讲述了如何在多于 6 个参数的情况下传参,观察栈帧的变化过程,你可以看看下面的图片和代码,回忆一下:
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文深入探讨了编译器后端工作的实质,重点介绍了从AST生成汇编代码的完整过程,包括函数调用和参数传递、加法运算的翻译逻辑以及代码优化。通过示例代码和详细解释,读者可以了解如何生成汇编代码,如何使用寄存器进行充分优化,以及整体的汇编代码生成逻辑。文章还提到了对playscript程序进行编译并生成可执行文件的过程,以及建议基于现有代码框架进行修改,增加其他特性。最后,挑战读者用playscript生成目标文件,让C语言来调用,以证明playscript生成汇编代码的逻辑可靠。此外,文章还介绍了链接过程和可执行文件的结构,为读者提供了对编译过程的全面理解。整体而言,本文是一份有价值的技术指南,对于想深入了解编译器后端工作的读者具有重要参考价值。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《编译原理之美》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(4)

  • 最新
  • 精选
  • 沉淀的梦想
    https://github.com/RichardGong/PlayWithCompiler/blob/d1f393d98000e8e9a7b22b870b690cd80de35bae/playscript-java/src/main/play/AsmGen.java#L470 这一行是不是应该改成`Function function = (Function) at.node2Scope.get(ctx);`,不然运行时会出现空指针异常

    作者回复: 是的,我后来似乎改过了。因为修改了一些语义分析的代码,使得一些类型信息不再保存在AnnotatedTree.typeOfNode中了。 我抽时间应该加上一些自动的测试用例,避免修改一个地方,让另一个地方break掉。

    2019-10-16
    2
  • humor
    cannot execute binary file 为什么我运行在mac上运行as命令后编译的机器码,会报这个错误呀

    作者回复: 这是我的疏漏。as是生成目标文件。需要再链接一下才能生成可执行文件。文稿我已经修改了!

    2020-03-19
  • 沉淀的梦想
    老师,栈顶为什么要16字节对齐呢?

    作者回复: 调用约定。 可以参考一下https://en.wikipedia.org/wiki/X86_calling_conventions "In Linux, GCC sets the de facto standard for calling conventions. Since GCC version 4.5, the stack must be aligned to a 16-byte boundary when calling a function (previous versions only required a 4-byte alignment.)" 如果不遵守这个调用约定,有些功能会出错。比如调试的时候。 还可以参考一下这篇:https://software.intel.com/en-us/forums/intel-isa-extensions/topic/291241

    2019-10-16
  • minghu6
    汇编的代码有些罗嗦,好多段的命名跟编译器生成似的. 有一个问题就是实例代码里有一个main标签里面的`subq $16, %rsp` 说是为了16对齐, 但main本身push了一个8byte的返回地址吧?
    2021-05-30
收起评论
显示
设置
留言
4
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部