【问题标题】:Implementing a simulator for a subset of x86为 x86 的子集实现模拟器
【发布时间】:2012-03-09 05:43:31
【问题描述】:

我希望为 x86 架构的指令子集实现一个模拟器。给定一个二进制文件,我希望将其反汇编并根据指令运行模拟。为此,需要查看指令的某些位来确定它是控制指令、算术指令还是逻辑指令,并且在此基础上,必须通过查看剩余位来推导操作的参数。一种明显但痛苦的实现方式是使用嵌套的 if-else/switch-case 语句。有人可以提出更好的实施方法吗?

【问题讨论】:

  • 您确实需要一个 switch-case 语句,但不完全是。检查查找表;抓取一个字节,调用该字节值的处理程序,处理程序读取操作数并返回,重复。

标签: c++ x86 simulation


【解决方案1】:

如果您缓存翻译的输出,则执行嵌套的 if/else 类型构造应该没问题。如果您在进行仿真,那么在程序中的所有静态指令中,动态指令将相对较少。所以最好的性能优化就是缓存翻译的输出,然后在动态指令执行时重用。最终您的缓存将填满,您需要清除它以获取新条目。但以某种方式缓存翻译更有意义,而不是一开始就尝试提出一种非常快速的翻译方法。

例如,QEMU 是一个仿真器,它支持各种针对性能进行了优化的目标。您可以在此处查看他们如何翻译 x86 指令:

https://github.com/qemu/QEMU/blob/master/target-i386/translate.c#L4076

如果 QEMU 对每条指令都这样做,性能会非常慢。但是由于缓存了结果,所以第一次翻译指令时有一个复杂的case语句并不重要。

【讨论】:

    【解决方案2】:

    您可以查看 x86 仿真器的源代码来找到这个想法的实现,已经完全编写和充实。

    你可以试试这个:http://www.dosbox.com/wiki/BuildingDOSBox#1._Grab_the_source

    如果这不起作用,请告诉我;有很多可供选择。

    一般来说,对于模拟器,我认为打开操作码是一种方法。另一种好的方法是一个 256 项的函数指针数组,对应于指令的第一个字节。与巨型开关或 if 块相比,这提供了更多的分离。当然你可以根据需要重复使用这些函数。

    【讨论】:

      【解决方案3】:

      使用查找表,可能采用std::map 的形式。

      【讨论】:

      • 对于可以运行数百万次迭代的东西,我认为您对性能比map 更感兴趣。至少,哈希表是首选,但即使这样也可能不是最佳选择。
      猜你喜欢
      • 1970-01-01
      • 2012-12-24
      • 2011-02-08
      • 1970-01-01
      • 2014-04-15
      • 2017-04-24
      • 2014-09-17
      • 1970-01-01
      • 2020-10-22
      相关资源
      最近更新 更多