模拟器是如何工作的?当我看到NES/SNES或C64模拟器时,我很震惊。
您是否必须通过解释特定的组装指令来模拟这些机器的处理器?还有什么?它们通常是如何设计的?
你能给那些对编写模拟器(特别是游戏系统)感兴趣的人一些建议吗?
模拟器是如何工作的?当我看到NES/SNES或C64模拟器时,我很震惊。
您是否必须通过解释特定的组装指令来模拟这些机器的处理器?还有什么?它们通常是如何设计的?
你能给那些对编写模拟器(特别是游戏系统)感兴趣的人一些建议吗?
当前回答
我知道这个问题有点老了,但我想在讨论中补充一些东西。这里的大多数答案都围绕模拟器解释它们所模拟的系统的机器指令。
然而,有一个非常著名的例外,称为“UltraHLE”(维基百科文章)。UltraHLE是有史以来最著名的模拟器之一,它模拟了商用任天堂64游戏(在家用电脑上表现不错),当时人们普遍认为这是不可能的。事实上,当UltraHLE诞生时,任天堂还在为任天堂64制作新游戏!
这是我第一次在印刷杂志上看到关于模拟器的文章,而以前我只在网上看到过它们的讨论。
UltraHLE的概念是通过模拟C库调用而不是机器级调用来实现不可能。
其他回答
添加@Cody Brocious提供的答案 在虚拟化环境中,您正在向虚拟机模拟一个新系统(CPU、I/O等),我们可以看到以下类别的模拟器。
解释:bochs是解释器的一个例子,它是一个x86 PC模拟器,它把来自客户系统的每条指令翻译成另一组指令(主机ISA的指令)来产生预期的效果。是的,它非常慢,它不缓存任何东西,所以每条指令都经过相同的周期。
动态仿真器:Qemu是一个动态仿真器。它可以实时翻译客户指令,也可以缓存结果。最好的部分是直接在主机系统上执行尽可能多的指令,这样模拟就更快了。正如Cody所提到的,它将代码划分为块(一个单独的执行流)。
静态模拟器:据我所知,没有静态模拟器可以帮助虚拟化。
模拟可能看起来令人生畏,但实际上比模拟容易得多。
任何处理器通常都有一个编写良好的描述状态、交互等的规范。
如果您根本不关心性能,那么您可以使用非常优雅的面向对象程序轻松地模拟大多数老式处理器。例如,X86处理器需要一些东西来维护寄存器的状态(简单),需要一些东西来维护内存的状态(简单),还需要一些东西来接收每个传入的命令并将其应用到机器的当前状态。如果您真的需要准确性,您还可以模拟内存转换、缓存等,但这是可行的。
In fact, many microchip and CPU manufacturers test programs against an emulator of the chip and then against the chip itself, which helps them find out if there are issues in the specifications of the chip, or in the actual implementation of the chip in hardware. For example, it is possible to write a chip specification that would result in deadlocks, and when a deadline occurs in the hardware it's important to see if it could be reproduced in the specification since that indicates a greater problem than something in the chip implementation.
当然,电子游戏的模拟器通常关心性能,所以它们不会使用简单的实现,它们还包括与主机系统的操作系统接口的代码,例如使用绘图和声音。
考虑到老式电子游戏(NES/SNES等)非常缓慢的性能,在现代系统上进行仿真相当容易。事实上,更令人惊讶的是,你可以下载一套SNES游戏或Atari 2600游戏,考虑到当这些系统流行时,免费访问每个卡带都是一个梦想。
我知道这个问题有点老了,但我想在讨论中补充一些东西。这里的大多数答案都围绕模拟器解释它们所模拟的系统的机器指令。
然而,有一个非常著名的例外,称为“UltraHLE”(维基百科文章)。UltraHLE是有史以来最著名的模拟器之一,它模拟了商用任天堂64游戏(在家用电脑上表现不错),当时人们普遍认为这是不可能的。事实上,当UltraHLE诞生时,任天堂还在为任天堂64制作新游戏!
这是我第一次在印刷杂志上看到关于模拟器的文章,而以前我只在网上看到过它们的讨论。
UltraHLE的概念是通过模拟C库调用而不是机器级调用来实现不可能。
是的,你必须“手工”解释整个二进制机器码的混乱。不仅如此,大多数情况下,您还必须模拟一些在目标机器上没有等效硬件的外来硬件。
简单的方法是一个接一个地解释指令。这工作得很好,但是很慢。一种更快的方法是重新编译——将源机器码转换为目标机器码。这比较复杂,因为大多数指令都不是一对一映射的。相反,您将不得不制定涉及额外代码的详细变通方案。但最终还是要快得多。大多数现代模拟器都是这样做的。
还可以查看Darek Mihocka的Emulators.com,获得关于jit指令级优化的建议,以及许多关于构建高效模拟器的其他好东西。