简单指令编码

问题描述

让我们接受以下汇编指令:

add    %cl,%bl

它被编码为:00 cb或二进制形式的00000000 11001011。将cb放入ModR / M位域,如下所示:

  1   1   0   0   1   0  1   1
+---+---+---+---+---+---+---+---+
|  mod  |    reg    |    r/m    |
+---+---+---+---+---+---+---+---+

然后,客栈在register field here中查找,我们得到:

  • mod:11(寄存器寻址模式)
  • reg:001(cl寄存器)
  • r / m:011(bl寄存器)

而且,我相信000000dsadd的指令,而d=s=0[empty] 0x0 0b11001011 [empty] [empty] [empty] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ Prefix Instruction Mod-reg-r/m Scale displacement immediate 的所有寄存器。这是对该指令编码方式的正确理解吗?此外,对于“完全编码”方案,以下内容是否准确(以字节为单位,不是位):

router.use('/route1',route1);
router.use('/route2',route2);
router.use('/route3',route3);

在尝试“解码”指令时,这里有什么我想念的东西吗?

解决方法

是的,看起来不错。

用于对op r/m,rop r,r/m进行编码以及8位vs. 16/32位的通用模式(可追溯到8086年的“传统” ALU指令)使用低2位以常规模式存储操作码字节,但无需依赖它。

英特尔确实在其第2卷手册中完全记录了每条指令的每种编码所发生的情况。例如,请参见“操作/ En”列和add的“操作数编码”表。 (另请参见https://ref.x86asm.net/coder64.htm,它也为每个操作码指定哪个操作数)。这些都可以让您知道哪些操作码需要ModRM字节,哪些不需要。

这些当然使用Intel语法顺序。尝试遵循手册和教程,同时使用AT&T语法,这会使操作数列表与Intel和AMD手册的顺序相反,从而使您的生活变得更加复杂。

例如00 /rlisted,与MR操作数编码一样,从表中我们可以看到它是操作数1 = {ModRM:r/m (r,w),因此它被读写,并由{{1 }}字段。操作数2 = r/m,因此它是由ModRM:reg (r)字段编码的只读源。

有趣的事实:reg00 00或AT&T add [rax],al

请注意,您可以要求GAS选择以下任一编码:x86 XOR opcode differences

add %al,(%rax)

另请参阅Difference between MOV r/m8,r8 and MOV r8,r/m8