【发布时间】:2010-10-16 21:02:38
【问题描述】:
对于一个拥有 10 到 20 年经验且从未构建过编译器或仿真器的熟练开发人员来说,哪个更具挑战性?
您能比较一下可能成为障碍的问题吗?
谢谢。
【问题讨论】:
标签: compiler-construction comparison emulation
对于一个拥有 10 到 20 年经验且从未构建过编译器或仿真器的熟练开发人员来说,哪个更具挑战性?
您能比较一下可能成为障碍的问题吗?
谢谢。
【问题讨论】:
标签: compiler-construction comparison emulation
断章取义,没有明确的答案:这完全取决于您想要实现的目标,以及您要竞争的目标。
如果它只是一个“概念证明”,那么在这两种情况下,它都相当简单。
但是,如果您想要模拟复杂的硬件或高精度,或者想要达到 AAA 编译质量,那么事情很快就会变得非常复杂。 复杂性不仅会出现在“主要”代码的算法/理论中,还会出现在您必须构建的所有支持工具(调试器、反汇编器、分析器等)中,以便您可以进入下一步。
也就是说,要考虑的另一个方面是,为几乎任何编程语言编写一个工作编译器都具有合理的复杂性。另一方面,如果有一些硬件可以轻松模拟,那么还有一些硬件即使是基本的模拟器也可能非常复杂。
所以用粗笔绘画,我会说编写编译器更容易,因为无论目标硬件或语言如何,你几乎可以保证成功获得工作版本。模拟器没有这样的保证。
【讨论】:
在我看来,复杂的编译器比复杂的模拟器更难编写,原因很简单,编译器涉及更多的理论。
在设计语言 XX 时,需要考虑很多因素,更不用说优化编译器生成代码的输出了,这本身就是一门黑魔法。使用模拟器,您就拥有了一个已经定义良好的环境,其中包含您想要实现的大部分定义良好的语言。
无论如何,我建议任何人编写和编写编译器,因为它可以让您更深入地了解编程,就像医生需要了解身体解剖学一样,即使他在日常工作中可能不需要它。
编辑:我认为这两种技能都非常有用,实际上可以将它们结合起来——它们不是异或。
我想补充一下我的上述观点是,创建一种非平凡的编程语言,包括运行时库以与驱动程序、数据库等交互,并且可以随着未来版本的发展而发展,但仍保持向后兼容,这是更具挑战性的语言之一CS领域。
我也同意,如果平台是未知的,即您正在对某些东西进行逆向工程,那么做一个模拟器要困难得多,但是 OTOH 这不是 OP 的问题,是吗?
【讨论】:
为已知的模拟平台编写模拟器并不难(您也可以使用预制的 CPU 模拟器并获得一些开发时间)。
为未知的仿真硬件编写一个模拟器要困难得多,并将难度转移到与代码开发不同的领域:数学、密码分析、安全协议等。而且,作为开发人员,你必须对过程中涉及的反复试验有耐心。
例如,想想CPS2 仿真需要多少时间(CPS2 ROM 已加密)。
【讨论】:
软件的模拟非常简单,相对容易,但可能很乏味。
编写编译器可能非常困难,但如果您具备良好的工作知识或拥有一组您正在为其编写编译器的语言的良好规范(例如 Backus-Naur 形式表示法),它就会变得更简单。
如果您的目标是让仿真器在许多不同的平台上工作(例如,在 MSDOS 下使用正确的 fudge 常量运行软盘驱动器时序仿真,但仿真失败),硬件仿真可能会非常困难在 Vista 或 Linux 等多任务平台上)。当没有足够的知识了解其操作模式如何由软件控制时,硬件仿真也极其困难。这迫使在取得进展之前进行漫长而烦人的逆向工程。
总而言之,我认为仿真更难。
【讨论】:
仿真和编译是完全不同的,但由于两者都被认为是“低级的”,所以往往会被混为一谈。
6502 或 Z80 等简单架构的仿真对于 CPU 工作块来说是相当简单的,但由于您需要为每条指令创建一个函数,因此需要编写大量代码。您将希望以某种方式从具有所有时序等的指令集规范中自动执行此操作,因为将这些全部输入确实非常乏味:) 旧的 CPU 指令集规范很容易找到,所以这很有帮助在构建模拟器时。
除此之外,您还需要实现某种程度的硬件仿真,这通常涉及处理和生成中断(例如,如果仿真器用于显示设备的垂直空白中断)比如游戏机)。这再次需要一定程度的规范和代码生成,但您可能必须手动编写大部分代码,因为它不会像指令集代码那样重复(因此可自动化)。
编译将涉及某种语言规范,无论您要为其实现编译器的任何语言,以及您要为其输出代码的目标。输出可以是直接的二进制,可以是汇编,甚至可以是另一种语言(这实际上只是一个翻译器,但当目标被认为是“足够”低级时,它算作编译)。由于您将在某种硬件或 VM 平台上运行,因此您不太可能需要担心中断处理之类的事情。
绊脚石是复杂性和正确性——除非你选择模拟器,否则你需要让它非常准确地工作非常简单的东西可以模仿。您还需要为模拟器创建某种集成调试器,否则当它总是这样做时,几乎不可能分辨出哪里出了问题。对于编译器而言,翻译一种玩具语言或一种更复杂语言的一小部分子集应该是相当简单的,并在你进行的过程中构建它。
请记住,对于这两个项目,您需要能够产生输入来测试它们,如果您不能产生简单的输入,那么您会发现从一开始就很难进行调试。 仅此一项就使编译器的工作更容易进入,恕我直言(那你会想要有一些可以立即模拟完整控制台或其他东西的东西:)
【讨论】:
我两者都写过,并且会说在其他条件相同(语言或指令集的复杂性)的情况下,编写模拟器方式更容易,特别是如果您正在尝试编写 有趣的模拟器或编译器。
原因是,您使用模拟器试图用另一个类似的低级事物来模拟低级事物。这还不错。使用编译器,您可能会尝试使用非常低级的工具(机器字和机器指令)来实现非常高级的想法(例如,对象、一等函数、托管内存、字符串扫描)。这项任务要困难得多。
当然,为了好玩,你可以编写一个模拟器,通过动态二进制翻译工作,即将模拟架构的机器代码编译成本地架构的机器代码。通过这种方式,您可以获得两者的所有乐趣 --- 并且您可以制作真正快速的模拟器,例如 QEMU 或已故的 Digital FX!32。
【讨论】:
我两者都写过,并且会说模拟器通常更容易。当然,这在很大程度上取决于您要模拟的内容(在 iPhone 上模拟 IBM 大型机可能有点挑战)以及您要编译的内容(小型 C 编译器非常简单,几乎可以使用完整的 C++ 编译器)太难了。
【讨论】:
这在很大程度上取决于您正在模拟什么以及您正在编译什么。
【讨论】:
编写编译器要困难得多,因为您要处理低级别的东西(链接、特定于您的体系结构的程序集等)。
仿真器只需要执行输入给它的每条指令的逻辑(我知道我正在简化这一点,但我假设您有指令集的规范),现在,编写 FAST 仿真器要困难得多。
【讨论】: