模拟x86处理器--如何开始?

8
最近我了解到Fabrice Bellard利用模拟i586的方式,使用JavaScript创建了QEMU的一个实现,这引起了我的兴趣。因为我一直被微处理器里内含的复杂性所吸引,所以希望能够完成一个x86模拟器的任务。但是显然,它可能不会像QEMU那么复杂,这并不是主要问题。
我有操作系统和低级编程的经验,另外还写过一些非常简单的CHIP8模拟器程序。我知道简单模拟器是如何工作的。在我开始开发x86处理器时,如何利用我目前的这方面知识?
同时,如果你已经完成了我正在努力尝试做的事情,我会非常感激您的任何建议。有哪些书籍应该放在我的桌子上?(请注意我喜欢书籍。)论文?网站我应该知道的?等等。
提前感谢。

所以...你想在x86上模拟一个x86?我不知道你是否能找到很多关于这个的书籍和论文。为了这个目的,直接在主机CPU上执行客户代码会更有意义。 - Johan Kotlinski
当然,那是最简单的方法。但是,由于我开始这个项目仅仅是为了学习它的工作原理,所以这不是我首选的方法。更像是映射操作码,模拟其他硬件,如8259,使其更适合我的目的等等。 - rotalume
如果@JohanKotlinski用C语言编写模拟器,那么它确实具有一定的意义。因为他可以将代码编译成不同的语言,比如ARM,然后瞬间!现在你就有了一个在ARM上运行X86的模拟器。我同意它并没有太多好处,但作为业余项目来考虑还是很不错的。 - Ajay Brahmakshatriya
1个回答

9
首先,你的真正目标是什么?你是想要一个准确的教育类型模拟器,还是想要一个vmware、qemu/kvm类型的快速模拟器,在后一种情况下利用主机处理器执行百分之几的指令(不进行模拟)。即使不想在主机上执行,但如果你对性能感兴趣(可能会牺牲准确性、可调试性或故障检测),请查看mame源代码,那里有一长串为了速度而编写的处理器模拟器。
我提到的那个是为了教育目的而编写的,特别是我自己和其他可能觉得有趣的人。对于这种类型的模型,我建议关注几个关键点。将内存读取、写入和获取操作抽象化(使用read_mem_8()函数和write_mem_8()等,就像硬件进行地址解码等)。同样,将寄存器读/写操作抽象成函数。模拟器围绕一个执行单个指令的函数展开,在循环中调用该函数以执行一定数量的指令或无限循环,或者介于两者之间,由你自己选择。这样你可以从前台或其他模式管理中断模式,而不是在负责指令解码的函数外部。指令解码器与反汇编器类似,不同之处在于对于变长指令集(如x86),你无需寻找指令的起始位置,而是通过执行来假设二进制代码是真实的并且可以执行,当然你需要有某种未定义指令处理程序。
由于许多原因,x86不会是我的首选。这里再次问一下你的目标是什么?x86将拥有32/64位模式、内存保护方案、许多执行模式等等。我会(并且已经多次)从简单的指令集开始,比如msp430、pic(旧版pic而非dspic或pic32)、6502等等。在mame世界中有许多6502 rom可以玩耍。(注意,一些6502模拟器存在漏洞)。msp430和pic只有少量指令,一旦掌握了技巧,就可以在一个下午内完成。如果你仍然觉得需要进行x86模拟,那么arm可能是迈向x86的一块垫脚石。各种执行模式,你可以根据需要模拟已知的mmu和fpu,并引导linux、windows等操作系统。

重新阅读您的问题,我可能过于简化了我的回答,听起来您有一些经验。在处理x86处理器时,与其他处理器没有什么不同,您需要编译一些简单的二进制文件,例如计数和循环,并攻击该二进制文件,解码和执行,增加测试程序的复杂性,将更多指令添加到模拟器中。在某个时候,这变得无聊,需要长时间的输入会话,逐步实现所有指令(不必测试每个指令)。然后返回并尝试执行更复杂的二进制文件(以尝试测试所有新指令)。我倾向于使用自检测试,例如压缩一些数据,然后使用开源软件包(编译为嵌入式)进行解压缩,并比较输入和输出。加密例程也很好,如aes、des等。md5、sha等不是自检的,但您可以在主机平台上预先计算答案,并在测试中硬编码答案。开放源代码jpeg、png等。mp3解码器。有定点jpeg和mp3解码器,或者您可以选择软fpu。不同的编译器产生不同的指令混合,某些编译器根本不使用某些指令或指令序列,因此强烈建议将这些测试程序重新编译并在该处理器上使用尽可能多的编译器以及几种不同的优化设置运行它们。不同的高级语言也应产生不同的指令混合。您可能会发现,单个程序员使用单个语言和单个编译器只会给您带来有限的覆盖范围,该人具有特定的编程习惯和风格,从而限制了输出的多样性,汇编程序也是如此。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接