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