70

我有兴趣将 x86 dissembler 编写为一个教育项目。

我找到的唯一真正的资源是 Spiral Space 的“如何编写反汇编程序”。虽然这对反汇编程序的各种组件进行了很好的高级描述,但我对一些更详细的资源感兴趣。我还快速浏览了NASM 的源代码,但这有点值得学习。

我意识到这个项目的主要挑战之一是我将不得不处理相当大的 x86 指令集。我也对基本结构、基本反汇编链接等感兴趣。

任何人都可以向我指出有关编写 x86 反汇编程序的任何详细资源吗?

4

5 回答 5

67

查看80386 Programmer's Reference Manual 的17.2 节。反汇编器实际上只是一个美化的有限状态机。拆解步骤如下:

  1. 检查当前字节是否为指令前缀字节(F3、、F2F0);如果是这样,那么你有一个REP// REPE/前缀REPNELOCK前进到下一个字节。
  2. 检查当前字节是否为地址大小字节 ( 67)。如果是这样,如果当前处于 32 位模式,则以 16 位模式解码指令其余部分中的地址,或者如果当前处于 16 位模式,则以 32 位模式解码地址
  3. 检查当前字节是否为操作数大小字节 ( 66)。如果是这样,如果当前处于 32 位模式,则以 16 位模式解码立即操作数,或者如果当前处于 16 位模式,则以 32 位模式解码立即操作数
  4. 检查当前字节是否为段覆盖字节(2E363E266465)。如果是这样,请使用相应的段寄存器而不是默认的段寄存器来解码地址。
  5. 下一个字节是操作码。如果操作码为0F,则为扩展操作码,读取下一个字节作为扩展操作码。
  6. 根据特定的操作码,读入并解码 Mod R/M 字节、比例索引基 (SIB) 字节、位移(0、1、2 或 4 字节)和/或立即值(0、1 、2 或 4 个字节)。这些字段的大小取决于先前解码的操作码、地址大小覆盖和操作数大小覆盖。

操作码告诉您正在执行的操作。操作码的参数可以从 Mod R/M、SIB、位移和立即值的值中解码。由于 x86 的复杂性,存在很多可能性和很多特殊情况。有关更详尽的说明,请参阅上面的链接。

于 2009-05-29T04:57:22.053 回答
22

我建议查看一些开源反汇编程序,最好是distorm,尤其是“disOps(指令集数据库)”(ctrl+在页面上查找)。

文档本身充满了关于操作码和指令的丰富信息。

引用自 https://code.google.com/p/distorm/wiki/x86_x64_Machine_Code

80x86 指令:

一条 80x86 指令被划分为多个元素:

  1. 指令前缀,影响指令操作的行为。
  2. 强制前缀用作 SSE 指令的操作码字节。
  3. 操作码字节,可以是一个或多个字节(最多 3 个完整字节)。
  4. ModR/M 字节是可选的,有时可能包含操作码本身的一部分。
  5. SIB 字节是可选的,表示复杂的内存间接形式。
  6. 位移是可选的,它是一个不同大小的字节(字节,字,长)的值,用作偏移量。
  7. 立即数是可选的,它用作从不同大小的字节(字节、字、长)构建的通用数值。

格式如下所示:

/-------------------------------------------------------------------------------------------------------------------------------------------\
|*Prefixes | *Mandatory Prefix | *REX Prefix | Opcode Bytes | *ModR/M | *SIB | *Displacement (1,2 or 4 bytes) | *Immediate (1,2 or 4 bytes) |
\-------------------------------------------------------------------------------------------------------------------------------------------/
* means the element is optional.

https://code.google.com/p/distorm/wiki/diStorm_Internals中解释了数据结构和解码阶段

引用:

解码阶段

  1. [前缀]
  2. [获取操作码]
  3. [过滤操作码]
  4. [提取操作数]
  5. [文本格式]
  6. [十六进制转储]
  7. 【解码指令】

还解释了每个步骤。


由于历史原因,保留原始链接:

http://code.google.com/p/distorm/wiki/x86_x64_Machine_Codehttp://code.google.com/p/distorm/wiki/diStorm_Internals

于 2009-05-29T04:41:55.553 回答
6

从一些已经组装好的小程序开始,它会为您提供生成的代码和指令。为自己获取指令架构的参考,并通过架构参考手动完成一些生成的代码。您会发现指令具有非常典型的inst op op op结构,具有不同数量的操作数。您需要做的就是翻译代码的十六进制或八进制表示以匹配指令;稍微玩一下就会发现。

该过程是自动化的,是反汇编程序的核心。理想情况下,您可能希望在内部(或在外部,如果程序非常大)构建指令结构数组。然后,您可以将该数组转换为汇编格式的指令。

于 2009-05-29T04:00:27.667 回答
4

您需要一个操作码表来加载。

基本的查找数据结构是 trie,但是如果您不太关心速度,则表会做得很好。

要获取基本操作码类型,请从表上的匹配开始。

有几种解码寄存器参数的常用方法;但是,有足够多的特殊情况需要单独实施其中的大部分。

由于这是教育性的,请查看 ndisasm。

于 2009-05-29T04:02:55.173 回答
2

检查 objdump源- 这是一个很棒的工具,它包含许多操作码表,它的源可以为制作自己的反汇编程序提供一个很好的基础。

于 2011-08-07T23:27:42.000 回答