ASM x64 中 40h REX 操作码的目的是什么?

c00*_*0fd 5 windows 64-bit x86-64 opcode disassembly

我一直试图了解0x40ASM x64 指令的REX 操作码的用途。例如,在 Kernel32.dll 的这个函数序言中:

在此处输入图片说明

如您所见,它们push rbx用作:

40 53      push        rbx 
Run Code Online (Sandbox Code Playgroud)

但仅使用53h操作码(不带前缀)也会产生相同的结果:

在此处输入图片说明

根据此站点,REX 前缀的布局如下:

在此处输入图片说明

所以40h操作码似乎没有做任何事情。有人可以解释它的目的吗?

Nat*_*man 4

这些04xh字节(即040h041h... 04fh)确实是 REX 字节。正如您在问题中列出的那样,下半字节中的每一位都有其含义。该值040h表示REX.WREX.RREX.XREX.B都是0。这意味着添加此字节不会对该指令执行任何操作,因为您不会覆盖任何默认的 REX 位,并且它不是以 AH/BH/CH/DH 作为操作数的 8 位指令。

而且, 、XRB都对应一些操作数。如果您的指令不消耗这些操作数,则相应的 REX 位将被忽略。

  • @c00000fd:是的,你错过了一些东西。Microsoft 使用冗余的 REX 前缀来使指令更长*而不是*使用单独的 NOP 指令。这使得代码运行得更快。[可以使用哪些方法来有效地扩展现代 x86 上的指令长度?](//stackoverflow.com/q/48046814)。当您进行热补丁时,您可以将一些早期指令替换为新代码的“jmp”,然后可能跳回到函数的其余部分。您链接的那篇文章与 5x 单字节 `nop` 指令是一个糟糕的计划;当您将其替换为“jmp”时,执行可能会在第二个“nop”上。 (2认同)
  • @Nathan:“0x40”对字节寄存器有影响:例如需要编码“mov al, sil”。(这就是为什么 AH/BH/CH/DH 无法在带有 REX 前缀的指令中进行编码,因此您无法编码 `mov ah, sil`)但是,对于 `push` 和除 8 位以外的任何操作码操作数大小指令,“0x40”是多余的。 (2认同)