学习编程语言的工作原理

时间:2009-10-04 08:41:48

标签: compiler-construction interpreter

我已经编程多年了(主要是Python),但我不明白在编译或执行代码时幕后会发生什么。

我之前问过question关于操作系统的问题,我正在寻找对编程语言工程的温和介绍。我希望能够定义和理解编译器,解释器,本机代码,托管代码,虚拟机等术语的基础知识。什么是一个有趣和互动的方式来了解这一点?

10 个答案:

答案 0 :(得分:12)

简单执行的代码

程序(代码)被输入编译器(或解释器)。

字符用于形成标记(+,标识符,数字),它们的值存储在称为符号表的某些内容中。

这些标记放在一起形成语句:(int a = 6 + b * c;)。主要是语法树的形式:

                     =
                    / \
                   /   \ 
                  a     +
                       / \
                      /   \
                     6     *
                          / \
                         b   c

在解释器中,树直接执行。

使用编译器,树最终会转换为中间代码或汇编代码。

您现在拥有一个或多个“目标文件”。它们包含没有精确跳转的汇编程序代码(因为这些值尚不清楚,特别是如果目标位于其他目标文件中)。 目标文件通过链接器链接在一起,链接器填充跳转的空白(ans引用)。链接器的输出是一个库(也可以链接)或可执行文件。

如果启动可执行文件,程序数据将被复制到内存中,还有一些其他链接可以将指针与正确的内存位置相匹配。然后控制第一条指令。

答案 1 :(得分:4)

编译器,解释器和虚拟机只是实现细节的示例。您可能寻找的是编程语言理论,生成语法,语言翻译,您可能需要一些计算机体系结构来将理论与实现联系起来。

就个人而言,我从Sebesta's book学到了什么。它对该主题进行了非常广泛的介绍,而没有详细介绍。它还有一个很好的章节编程语言的历史(约20种语言〜每种语言3篇论文)。它总体上对语法和语言理论有很好的解释。此外,它还对Scheme,Prolog和编程范例(逻辑,功能,命令式^,面向对象)进行了很好的介绍。

^它比前两个更集中于命令式范式。

答案 2 :(得分:4)

基本来说,你写source files。这些是花哨的文本文件,由compiler接收,输出某种形式的可执行代码(执行它的内容取决于您所讨论的代码类型)。编译器有几个部分:

  • 文件中某种形式的preprocessing处理宏等(如C)。
  • A parser,它接收源文件,验证它们是否符合您语言的语法规则,并将文件转换为内存数据结构,该结构更容易被程序的其他部分操作。这称为Abstract Syntax树或AST。
  • 某种形式的AST分析,它验证您编写的实际代码不会违反任何语言规则(例如,使用不支持语言的语言进行递归),以及许多其他内容。
  • Optimization,例如尾调用优化,循环优化和许多其他类型的优化。
  • Code generation,这是获取最终AST和任何其他生成数据并将其转换为某种可执行或解释的二进制文件的实际过程。

Interpreter:

解释器是一种程序,它接收某种形式的二进制数据,表示未编译为目标机器可直接执行的代码的程序,并在其中运行命令。示例是python,java和lua。

Native code:

这是已编译为可由目标机器直接执行的本机指令的代码。例如;如果你在x86架构上运行,那么c ++将编译成一个处理器可以理解的可执行文件。

Virtual Machine:

这通常是为模拟处理器的构造和操作而构建的程序。它可能像读取bytecode的程序一样简单,并根据字节码所代表的命令运行本机语言操作(虽然称这是虚拟机可能是一个延伸),或者它可能像完全模拟一样复杂处理器和所有相关外围设备的行为。

其他答案中有好点,但这些信息和链接应该让你开始。还有其他问题,请问!

(本文的大部分内容是在维基百科的帮助下编写的,尽管有些是从内存中编写的)

答案 3 :(得分:3)

This site has a great series关于计算机程序结构和解释的讲座,这正是你想要学习的东西。附带的教科书也很有用,因为我没有亲自阅读整篇文章。我认为观看讲座非常好,让你大约60%的路程。

答案 4 :(得分:2)

哇,这是一个很大的问题,关于这一切都有大量的书籍。我真的怀疑你会在这方面得到一个体面的答案。你需要到当地的书店或参加一些comp sci课程。

为您提供快速介绍:

  • 编译器:将编写的代码转换为处理器本身可以理解的指令的程序。
  • 口译员:一个程序,可以读取已编写的代码,并且即时翻译并提供相应的处理器本机指令。
  • 托管代码:在虚拟机中运行的代码,例如提供跨平台兼容性(Java)。
  • 虚拟机:一个程序,它模拟完整计算机环境的行为,或者更确切地说是API。除此之外,这提供了一些安全优势和跨平台兼容性。

答案 5 :(得分:2)

http://en.wikipedia.org/wiki/Dragon_Book_(computer_science)会解释很多这些概念,你应该读一读,这对我来说是一个真正的大开眼界。

答案 6 :(得分:2)

如果您想知道从源代码到实际在目标计算机上运行的内容,您应该获得着名的Red Dragon Book的副本。我用它来构建解析器和词法分析器。虽然它可以追溯到1986年,我确信在过渡期间已经取得了进展,据我所知,它并没有被超越作为文本。

Addison-Wesley似乎已经完成了其前身“绿龙书”的转载,并将其作为最近的内容传递出来,所以要小心获得真品。

答案 7 :(得分:1)

当我在上个世纪下半叶的某个地方学习编程时,我了解到所有东西都需要转换为机器代码。脚本语言将根据脚本代码决定调用哪些代码。编译代码首先被编译为p代码,代表预编译代码,需要链接到其他预编译代码以创建完整的应用程序。我当时喜欢Turbo Pascal,仅仅是因为Turbo Pascal直接编译为machione代码并且它没有使用中间的p代码。也就是说,直到Turbo Pascal 4.0,它创建了* .tpu编译单元。大多数其他编译器将编译为.obj格式。

创建Java时,相对较新的东西开始流行起来。基本上,Java编译器只是将代码编译为某个二进制脚本文件。然后可以解释此脚本,尽管该机制很快也会改变。

如今,口译员几乎绝迹。大多数脚本语言将首先编译为机器代码,然后将机器代码存储在某个缓存中,因此可以快速执行,而系统不必重新解释任何重复指令。这适用于文本和二进制脚本。 PHP将是基于文本的脚本的示例。 Java和.NET是二进制脚本,因为您通常将代码编译为此二进制脚本格式。 (他们会称之为不同,但我认为二进制脚本听起来更好。)

通常,诀窍是使用任何可能的方法将代码转换为机器代码。有很多方法可以做到这一点,而且要清楚地说明这一点有点复杂。

我还记得我编写C ++应用程序的时候,其中SQL语句将位于代码本身内部。这也非常实用,但它需要一个预处理器,它首先解析代码中的SQL语句,将其转换为其他C ++语句,并将SQL语句替换为那些更复杂的C ++命令。然后整个事情将被编译为p代码。然后你需要将它与其他SQL库链接,最后你有一个可执行文件。

答案 8 :(得分:1)

斯坦福大学的这个series of lectures涵盖了几种编程语言,包括Python(虽然我只看了几个C语言)。

答案 9 :(得分:0)

你可以找到很多讲座。例如在Itunes U