-4

Recently I have been extremely interested in language development, I've got multiple working front ends and have had various systems for executing the code. I've decided I would like to try to develop a virtual machines type system. (Kind of like the JVM but much simpler of course) So I've managed to create a basic working instruction set with a stack and registers but I'm just curious about how some things should be implemented.

In Java for example after you've written a program you compile it with the java compiler and it creates a binary (.class) for the JVM to execute. I don't understand how this is done, how does the JVM interpret this binary, what's the transition from human readable instructions to this binary, how could I create something similar?

Thanks for any help/suggestions!

4

3 回答 3

2

好吧,我会咬这个通用的问题。

实现编译器/汇编器/vm 组合是一项艰巨的任务,尤其是如果您自己做的话。话虽这么说:如果您的语言规范足够简单,那是完全可行的;也由你自己。

基本上,要创建二进制文件,请执行以下操作(这有点简化*:

1) 输入源被读取、词法分析和标记化

2) 分析程序逻辑的语义正确性。

例如,虽然下面的 C++ 会解析和标记化,但它会导致语义分析失败

float int* double = const (_identifier >><<) operator& * 

3)构建一个抽象语法树来表示语句

4) 建立符号表并解析标识符

5)可选:代码优化

6) 以您选择的输出格式生成代码;例如二进制操作码/操作数、字符串表。无论哪种格式最适合您的需求。或者,您可以为现有 VM 或本机 CPU 创建字节码。

编辑 如果您想设计自己的字节码格式,您可以编写,例如:

1) File Header
DWORD filesize
DWORD checksum
BYTE  endianness;
DWORD entrypoint <-- Entry point for first instruction in main() or whatever
2) String table
DWORD numstrings
<strings>
DWORD stringlen
<string bytes/words>

3) Instructions
DWORD numinstructions
<instructions>
DWORD opcode
DWORD numops <--- or deduce from opcode
DWORD op1_type <--- stack index, integer literal, index to string table, etc
DWORD operand1
DWORD op1_type
DWORD operand2
...

结尾

总的来说,这些步骤是可控的,但一如既往,魔鬼在细节中。

一些很好的参考资料是:

龙书- 理论很重,所以读起来很枯燥,但值得

Game Scripting Mastery - 指导您以更实际的方式开发所有三个组件。但是,示例代码充斥着安全问题、内存泄漏和整体糟糕的编码风格(恕我直言)。但是,您可以从这本书中学到很多概念,值得一读。

The Art of Compiler Design - 我没有亲自读过这篇文章,但听说过一些积极的事情。

如果您决定走这条路,请确保您知道自己会陷入什么困境。这不是胆小的人,也不是编程新手。它需要大量的概念思考和事先计划。然而,这是非常有益和有趣的

于 2013-09-11T23:50:47.137 回答
1

@APott-

1) 虚拟机不创建二进制文件。Java 编译器创建二进制 .class 文件;正在运行的 JVM 加载并执行类文件。

2) Java JVM 没有什么特别“新”或独特的地方。从概念上讲,它与 UCSD Pascal 或 IBM MV/370 没有什么不同。这是VM的简短历史:

3)如果你有兴趣,完整的JVM规范在线,并且有很多书籍/链接详细讨论它:

于 2013-09-11T22:43:08.610 回答
0

编译器所做的只是将字符串转换为字符串,无论目标是真机还是虚拟机。由于您正在构建自己的目标 VM,因此您可能会使用与现有虚拟机或物理机指令集不同的编码方式,但这并没有真正改变。所有物理机指令集都可以在软件中模拟,所有虚拟机指令集都可以在硬件中运行(尽管这在实践中可能会稍微困难一些,因为为虚拟机设计的指令集可能比硬件预算允许的复杂得多)。毕竟,CPU 只是指令集的解释器。

任何编译器书籍都应该对此进行扩展,但是物理机或虚拟机的编译过程是相同的。通常,您需要首先将源语言解析为源代码抽象语法树 (AST),然后需要翻译将源 AST 转换为目标 AST(尽管目标语言通常比源语言更扁平,所以你可能实际上不需要一棵树,但一个数组通常就足够了),那么你需要代码生成将目标 AST 转换为字节码(这通常只是从目标 AST 节点到字节码的一对一转换)。对于语法复杂的语言,您可能需要有中间解析阶段来形成具体的语法树,也就是解析树,然后才能形成源 AST;一些编译器可能使用多个翻译阶段,并且可能在其间包含一个优化翻译器;这些是微小的差异。

于 2013-09-11T23:40:41.573 回答