即使您可以直接访问硬件寄存器,将代码包装在使用寄存器而不是内存的决定上也会慢得多。
要获得性能,您需要预先设计性能。
几个例子。
通过设置所有陷阱来准备 x86 VM,以捕获离开其虚拟内存空间的代码。直接执行代码,不要模拟,分支到它并运行。当代码超出其内存/i/o 空间以与设备等进行通信时,捕获并模拟该设备或它所到达的任何东西,然后将控制权返回给程序。如果代码受处理器限制,它将运行得非常快,如果受 I/O 限制,则速度会很慢,但不如模拟每条指令那么慢。
静态二进制翻译。运行前反汇编和翻译代码,例如指令 0x34,0x2E 将在 .c 文件中转换为 ascii:
人^= 0x2E;=0; cf=0;sf=al
理想情况下执行大量的死代码删除(如果下一条指令也修改了标志,那么不要在此处修改它们,等等)。并让编译器中的优化器完成其余的工作。您可以通过这种方式在模拟器上获得性能增益,性能增益的好坏取决于您可以优化代码的程度。作为一个新程序,它在硬件上运行,注册内存等等,因此处理器绑定的代码比 VM 慢,在某些情况下,您不必处理处理器执行异常以捕获内存/io,因为您已经模拟了内存在代码中访问,但这仍然需要成本,并且无论如何都会调用模拟设备,因此那里没有节省。
动态翻译,类似于 sbt 但您在运行时执行此操作,我听说过此操作,例如在其他处理器上模拟 x86 代码时,例如 dec alpha,代码从 x86 指令慢慢更改为本机 alpha 指令,所以下一次它直接执行 alpha 指令,而不是模拟 x86 指令。每次通过代码程序执行得更快。
或者,也许只是重新设计你的模拟器,从执行的角度来看更高效。以 MAME 中的模拟处理器为例,代码的可读性和可维护性已经牺牲了性能。写这点很重要,今天使用多核千兆赫处理器,您不必费力地模拟 1.5ghz 6502 或 3ghz z80。像在表格中查找下一个操作码并决定不模拟指令的部分或全部标志计算这样简单的事情可以给您带来明显的提升。
底线,如果您有兴趣在运行程序时使用 x86 硬件寄存器、Ax、BX 等来模拟 AX、BX 等寄存器,那么唯一有效的方法是实际执行指令,而不是执行和陷阱就像在单步调试器中一样,但在执行长串指令的同时防止它们离开 VM 空间。有不同的方法可以做到这一点,性能结果会有所不同,这并不意味着它会比性能高效的模拟器更快。这限制了您将处理器与程序匹配。使用高效的代码和非常好的编译器(好的优化器)模拟寄存器将为您提供合理的性能和可移植性,因为您不必将硬件与正在运行的程序相匹配。