Update on 2013-01-16: 在 Dawson Engler 的主页上看到一篇论文,Reverse-Engineering Instruction Encodings,利用系统的汇编器自动生成指令 encoding 信息。有了这个信息就可以写 code generator, disassembler 了。Dawson 在这篇 paper 的说明里写道:
It’s genesis was the fact that writing a binary encoder for the x86 is an unredeemably disgusting experience.
我想说,写 x86 的反汇编器是一样的感受。
折腾了 QEMU 两年多,看到 Bellard 大神用 Javascript 写的 x86 模拟器后也曾想用 Go 写一个 x86 的模拟器。
2012 年的时候花了些时间从反汇编 x86 指令开始写,写着写着就没有动力继续下去了。想要模拟 x86 指令集非常麻烦,光是反汇编和 condition code 处理就包含了大量无趣的体力活。暂时不会有兴趣继续这个项目了。(或许开始时应该采纳实验室同学的建议选一个简单一些的体系结构来模拟,例如任天堂的游戏机,不过因为懒得去学其他体系结构而没有采纳。)
不过这个半途而废的项目倒是让我更加了解 x86 的指令。这篇博客就分享一些当时找到的关于 x86 指令集的资料和发现吧。
- x86 Opcode Structure and Instruction Overview 这个 pdf 文件非常清楚的展示了 x86 指令的分组情况,即使你对写反汇编器没有兴趣也可以看一下
- 从上面的 pdf 文件来看 x86 的指令编码其实还是有些规律的,反汇编器可以用 data driven 的方式来实现。不过由于 x86 指令有很多例外,所以需要加很多特殊情况处理代码
- diStorm Powerful Disassembler Library For x86/AMD64 这是一个很不错的 x86 反汇编库,有 Python binding
- diStorm’s introduction to x86 x64 machine instruction
- diStorm 的这篇文章很好的介绍了 x86 指令的编码方式,这篇文章好在它解释了某些看起来很奇怪的编码方式背后的原因
- X86-64 Instruction Encoding
- x86-64 Tour of Intel Manuals
前面提到这些文档都比较容易理解,可以对 x86 指令的编码方式有一个整体的了解。当想要了解具体某条指令的编码和含义时,Intel® 64 and IA-32 Architectures Software Developer’s Manual 是最权威的官方文档。其中 Volume 2: Instruction Set Reference 是专门介绍指令的。
- Volume 2C 附录 B.2 包含了每一条指令的二进制编码形式
- Volume 2C 2.1.3 关于 ModR/M byte 的说明,这个字节指定了指令的寻址模式,有时候会作为指令的 extension
我自己做的一些笔记对阅读这些文档会有一定的帮助。
最后还是把没写完的代码放出来吧,见 github。