我已经编程多年了(主要是Python),但我不明白在编译或执行代码时幕后会发生什么。
我之前问过question关于操作系统的问题,我正在寻找对编程语言工程的温和介绍。我希望能够定义和理解编译器,解释器,本机代码,托管代码,虚拟机等术语的基础知识。什么是一个有趣和互动的方式来了解这一点?
答案 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接收,输出某种形式的可执行代码(执行它的内容取决于您所讨论的代码类型)。编译器有几个部分:
解释器是一种程序,它接收某种形式的二进制数据,表示未编译为目标机器可直接执行的代码的程序,并在其中运行命令。示例是python,java和lua。
这是已编译为可由目标机器直接执行的本机指令的代码。例如;如果你在x86架构上运行,那么c ++将编译成一个处理器可以理解的可执行文件。
这通常是为模拟处理器的构造和操作而构建的程序。它可能像读取bytecode的程序一样简单,并根据字节码所代表的命令运行本机语言操作(虽然称这是虚拟机可能是一个延伸),或者它可能像完全模拟一样复杂处理器和所有相关外围设备的行为。
其他答案中有好点,但这些信息和链接应该让你开始。还有其他问题,请问!
(本文的大部分内容是在维基百科的帮助下编写的,尽管有些是从内存中编写的)
答案 3 :(得分:3)
This site has a great series关于计算机程序结构和解释的讲座,这正是你想要学习的东西。附带的教科书也很有用,因为我没有亲自阅读整篇文章。我认为观看讲座非常好,让你大约60%的路程。
答案 4 :(得分:2)
哇,这是一个很大的问题,关于这一切都有大量的书籍。我真的怀疑你会在这方面得到一个体面的答案。你需要到当地的书店或参加一些comp sci课程。
为您提供快速介绍:
答案 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