我需要快速纠正这个 x86 操作码难题

逆向工程 部件 二元分析 x86 机器码
2021-06-30 09:29:00

我试图弄清楚如何对指令进行编码MOV DS, AX,但我对操作码表感到困惑,如下所示:

在此处输入图片说明

  1. 是 MOV DS 全是一个字节,还是 MOV 一个字节,DS 是第二个,AX 是第三个?

  2. 该表是否暗示源寄存器前缀 DS 的二进制值是 011?如果是这样,我将如何将其编码为整个指令的一部分?

我无法理解这些表格的列出方式如何有意义;他们应该更具体!任何人都可以解决这个问题吗?

我只想将值从 AX 寄存器移动到数据段 DS。没有网站完美地解释了操作码中寄存器的编码如何工作或重定位。

所有表格都来自http://ref.x86asm.net,非常模糊、不清楚、不具体和不详细。

我想知道是否有任何关于每个字节的编码、每个寄存器的值、地址截断、偏移量等的 100% 详细、完美解释的教程以二进制方式工作,以及如何以正确的方式对其进行编码。

1个回答

如果您熟悉编码的工作方式,那么该站点很好,但如果您刚刚开始,我会暂时跳过它。

最好的起点可能是 Intel 的架构软件开发人员手册查看第 2 卷中的第 2 章指令格式以及附录,特别是附录 B 指令格式和编码和附录 A 操作码映射。它们非常详细地描述了如何解码指令。

一旦您对指令编码的某些部分有所熟悉,指令列表页面中的符号就会开始变得有意义。例如,让我们检查您需要的那个。

在 页面上MOV,找到您需要的变体。这个看起来像这样:

Hex     Mnemonic          Encoding   Description
8E /r   MOV Sreg,r/m16**  RM         Move r/m16 to segment register.

在下表中查找“RM”,我们得到:

Op/En Operand 1     Operand 2     Operand 3 Operand 4
RM    ModRM:reg (w) ModRM:r/m (r) NA        NA

所以我们可以开始组装操作码。

第一个字节固定为8E.

第二个字节是 ModRM 字节。它由三个字段组成:mod,regr/m让我们在 Sandpile这张漂亮的桌子的帮助下组装它

首先是mod场地。由于我们的第二个操作数是寄存器而不是内存引用,因此这对应于mod=11

RM编码行我们看到reg编码第一个操作数,在我们的例子中DS在表中查找,我们可以看到它DS被编码为011.

最后是r/m字段编码操作数2,即AX它被编码为000.

所以我们的 ModRM 字节是11:011:000, 或D8这使得完整的操作码为8E D8. 你可以用你最喜欢的反汇编程序检查它,例如 XED:

>xed.exe -d 8E D8
8ED8
ICLASS: MOV   CATEGORY: DATAXFER   EXTENSION: BASE  IFORM: MOV_SEG_GPR16   ISA_SET: I86
SHORT: mov ds, ax

(顺便说一句,/r编码行中符号告诉我们,regModRM 字节字段对寄存器进行编码,而不是操作码扩展。在后一种情况下,符号将有一个/<digit>符号 where 是reg字段的值)。