编译原理实战课
宫文学
北京原点代码 CEO
26065 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 55 讲
真实编译器解析篇 (19讲)
编译原理实战课
15
15
1.0x
00:00/00:00
登录|注册

05 | 运行时机制:程序如何运行,你有发言权

操作数栈
栈帧
JVM栈
栈和堆
静态数据区
代码区
指令执行阶段
缓存命中率
编译后代码优化
读写速度
字节码指令集
寄存器
JVM
内存管理
逻辑内存
寻址空间
功能单元
高速缓存
寄存器
寄存器机
栈机
内存
CPU
知识综合
环境理解
程序执行模式
虚拟机
JVM
操作系统
并发调度
垃圾收集
虚拟机模式
物理机模式
参考资料
一课一思
课程小结
运行时系统
程序运行环境
运行时机制

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

你好,我是宫文学。在语义分析之后,编译过程就开始进入中后端了。
经过前端阶段的处理分析,编译器已经充分理解了源代码的含义,准备好把前端处理的结果(带有标注信息的 AST、符号表)翻译成目标代码了。
我在第 1 讲也说过,如果想做好翻译工作,编译器必须理解目标代码。而要理解目标代码,它就必须要理解目标代码是如何被执行的。通常情况下,程序有两种执行模式。
第一种执行模式是在物理机上运行。针对的是 C、C++、Go 这样的语言,编译器直接将源代码编译成汇编代码(或直接生成机器码),然后生成能够在操作系统上运行的可执行程序。为了实现它们的后端,编译器需要理解程序在底层的运行环境,包括 CPU、内存、操作系统跟程序的互动关系,并要能理解汇编代码。
第二种执行模式是在虚拟机上运行。针对的是 Java、Python、Erlang 和 Lua 等语言,它们能够在虚拟机上解释执行。这时候,编译器要理解该语言的虚拟机的运行机制,并生成能够被执行的 IR。
理解了这两种执行模式的特点,我们也就能弄清楚用高级语言编写的程序是如何运行的,进而也就理解了编译器在中后端的任务是什么。接下来,我们就从最基础的物理机模式开始学习吧。

在物理机上运行

在计算机发展的早期,科学家们确立了计算机的结构,并一直延续至今,这种结构就是冯·诺依曼结构。它的主要特点是:数据和指令不加区别,混合存储在同一个存储器中(即主存,或叫做内存);用一个指令指针指向内存中指令的位置,CPU 就能自动加载这个位置的指令并执行。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文深入介绍了程序在物理机和虚拟机上的执行模式,以及编译器在中后端的任务。文章详细解释了计算机的基本运行原理,包括CPU的构成和指令的执行方式,以及内存的使用模式。对于CPU的介绍包括寄存器、高速缓存和功能单元的作用,以及指令的机器码表示和汇编代码示例。此外,还提到了操作系统的分时调度机制。文章通过图文并茂的方式,生动地解释了计算机的运行机制,为读者提供了直观的认识。另外,文章还介绍了内存的寻址空间、虚拟内存机制以及栈和堆两种内存使用方式。对于栈,文章详细解释了栈帧的结构和栈的动态管理机制;对于堆,文章介绍了堆内存的申请和释放方式,以及与栈的区别和适用场景。总的来说,本文内容深入浅出,适合读者快速了解程序运行机制的基本原理,以及内存的使用模式和管理方式。文章还介绍了虚拟机的两种模型:栈机和寄存器机,以及它们的特点和应用场景。这些内容对于理解程序的执行模式和编译器的影响具有重要意义。文章还提到了一些具体的虚拟机实现,如JVM和Python的解释器,以及它们的运行机制和指令集。总的来说,本文内容涵盖了程序执行模式、编译器任务和虚拟机实现等多个方面,为读者提供了全面的技术视角。

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

全部留言(11)

  • 最新
  • 精选
  • 蹦哒
    老师请问: 1.iOS开发中的Object-C以及swift,也是属于栈机吧? 2.保存在栈帧中的寄存器信息,在函数调用结束之后,是怎样被恢复到寄存器中的呢?

    作者回复: 1.Objective-C和Swift,应该都是直接编译成机器码执行的,不属于栈机。它们后端都是依赖于LLVM。LLVM的主要发起者之一,也是Swift语言的设计者之一。 2.在为一个函数生成目标代码(比如汇编代码)的时候,在开头部分和结尾部分会做一些固定的工作。开头部分通常叫做“序幕”(prologue),在这里会设置栈顶指针,把某些该保护的寄存器入栈等操作。而结尾部分通常叫做“尾声”(epilogue),会做跟序幕相反的操作。这里被保护的寄存器是被调用者(callee)需要保护那些寄存器,叫做被调用者责任。 另外,在调用函数前后也是一样,调用者要把另一些寄存器保护起来,防止被被调用者破坏,这叫做调用者(caller)责任。

    2020-06-25
    5
  • ヾ(◍°∇°◍)ノ゙
    现在.net core 貌似发展趋势也越来越好,有空会讲讲嘛?

    作者回复: 篇幅限制,不能去设计每个编译器:-) 微软的产品往往都在易用性方面做得不错。 .NET在很多方面,也在计算机语言的设计领域做出了贡献。 微软换了新CEO以后,在开放性、拥抱开源方面做得越来越好了。

    2020-06-12
    2
  • Jxin
    半路出家学编译原理真吃力。基本看不懂,不过隐约觉得很重要,也有比较强的兴趣(这么秀的东西看不懂实在挠心)。去补编译原理之美了。看来得下一番功夫咯。

    作者回复: 加油! 什么都比不过一颗执着的心!

    2020-06-11
    2
  • 茶底
    最近正好在看asm字节码框架。可以互相印证。

    作者回复: Great!

    2020-06-10
    2
  • humor
    看有的资料上说进程的用户态内存段除了代码段,数据段,堆以及栈之外还有一个文件映射段,但是我看老师的图里怎么没有文件映射段呢?是省略掉了吗

    作者回复: 具体到每种操作系统(Windows,Linux和MacOS)、每种二进制标准,其内存分配和布局都不一样。针对不同的标准,链接程序生成的结果不同,加载程序加载到内存后的布局也不一样。 课程里是讲一些共性。 通常,仅仅写编译器,可以忽略一些二进制的细节,因为这是链接程序和加载程序的工作。如果想要了解,那就去查具体的标准。

    2020-06-12
    1
  • chris
    请问老师,v8的字节码有类似java字节码的规范吗?

    作者回复: 有一个“Ignition: V8 Interpreter”的设计文档可以参考: https://docs.google.com/document/d/11T2CRex9hXxoJwbYqVQ32yIPMh0uouUZLdyrtmMoL44/edit# 由于v8的字节码只是自己使用,所以没有必要制定公共的标准规范。

    2020-06-10
    1
  • 一课一思里的问题: 程序使用栈,无非是编译器最后生成了与栈操作相关的机器指令(PUSH、POP、根据bsp+偏移地址访问栈内局部变量),这个过程貌似只跟CPU有关,操作系统还会介入栈的管理吗? 我唯一能想到的是,在线程切换的时候,OS调度器 会将 被切换线程的上下文(比如CPU寄存器里的内容)先存到这个线程的栈里,等将来这个线程被切换回来的时候,再将它的上下文恢复,从栈里把数据刷回到CPU寄存器中,让这个程序从它刚才被打断的位置继续执行下去。 整个上下文context的save/restore过程,都是OS scheduler背后做的,线程本身是无感知的。

    作者回复: 风最近提了不少问题,我腾出空来逐一解答哈! 第一,你第一句准确地描述出了问题的关键,但可惜你没挖掘出答案。栈内存的管理中,CPU和操作系统到底扮演了啥角色? 第二,操作系统切换线程上下文的过程,你说的是对的。有一个小瑕疵:线程上下文不是保存在线程栈里,而是保存在内核里的。你可以想想这有啥道理? 这节思考题的参考答案,我放在了下一节的评论区里,你可以去看看。

    2020-11-15
  • Black
    关于每课一答,如果是连续分配的内存实现的栈,那应该比较简单,修改栈顶指针实际上也就是在栈顶的地址上加固定的偏移量,指向栈内的下一块内容。 如果是非连续的,那应该类似链表,我们修改栈顶指针,而指向的内容由操作系统负责,可能是链表结构,也可能维护了一个映射表(存储栈每一层对应的地址),不知道理解对不对。

    作者回复: 参考答案放到了下一节的评论区里了。你可以看一下:-)

    2020-09-15
  • 浩仔是程序员
    老师,像Java虚拟机本质上也是一个进程,本身也是像c语言运行的内存布局吧?文中说到java语言有自己的内存布局,这指的是在堆中又定义的一种内存数据结构吗?
    2023-01-12归属地:广东
    1
  • 林先森
    老师,JVM也是由C或者C++开发的应用程序,所以JVM本身也内存布局也是C的内存布局,文中说到Java语言有自己的内存布局,这里的内存布局是C在C内存布局中的堆上定义的一种内存数据结构吗?
    2023-04-29归属地:浙江
收起评论
显示
设置
留言
11
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部