assembly - x86 XOR 操作码差异

标签 assembly x86 bit-manipulation opcode instruction-encoding

看着 http://ref.x86asm.net/coder32.html我找到了两个与语句匹配的操作码

异或 eax,eax

1) 操作码 31 异或 r/m16/32 r16/32

2) 操作码 33 异或 r16/32 r/m16/32

两者都是指操作数 1 和操作数 2 的 32 位寄存器。那么,在 XORing 两个 32 位寄存器的这种特定情况下有什么区别吗?

最佳答案

x86 有 2 种冗余方法来编码任何基本 ALU 指令(可追溯到 8086)的 2 寄存器实例,使用 r/m 源和 r/m 目标形式。reg,reg 的这种冗余编码是 x86 机器代码如何允许大多数指令的内存目标或内存源的结果:而不是在 ModR/M 字节中花费位来对两个操作数进行灵活的编码,大多数情况下只有两个单独的操作码指示。
(这就是为什么任何指令都不允许使用两个显式内存操作数,例如 xor [eax], [ecx]Only a few instructions 其中一个或两个内存操作数是隐式的,例如 rep movspush [mem] 允许两个内存操作数,从不允许一条指令具有两个单独的 ModR/M 编码寻址模式。)

编码有模式
请注意 31对比 33用于 word/dword/qword 大小 xor仅在位 #1 上有所不同。其他说明如 29对比 2B sub遵循相同的模式。 位 #1 有时被称为操作码的“方向”位 . (不要与 EFLAGS 中的 DF(方向标志)混淆。
另请注意,这些指令的字节与字/双字/qword 操作数大小版本仅在低位不同,例如 30 XOR r/m8, r8对比 31 XOR r/m16, r16 .同样,这种模式出现在可追溯到 8086 的 ALU 指令编码中。这些操作码的第 0 位有时称为“大小”位。
这些具有每个方向和大小组合编码的“基本 ALU”指令可以追溯到原始 8086;许多后来的指令,如 386 bsf r, r/m 186 imul r, r/m, imm 没有可以允许内存目的地的形式。或为 bt* r/m, r 只有目的地可以是 reg/mem。
这也是为什么后来的指令(或它们的新形式,如 imul)通常没有单独的字节操作数大小操作码,只允许通过普通前缀机制的 word/dword/qword。 8086 占用了大部分编码空间,后来的扩展希望为更多 future 的扩展留出空间。所以这就是为什么没有 imul r, r/m8 .
(dword 和 qword 操作数大小本身就是扩展;8086 没有操作数大小或 REX 前缀。因此,原始 8086 在使用其操作码编码空间方面相当明智,并且具有使解码不会一团糟的模式。)

表单之间没有执行差异
对于 reg,reg 指令,它们在我知道的任何 CPU 上解码和执行的方式没有区别;唯一需要关心汇编程序使用哪种编码的时候是当您希望机器代码满足其他一些要求时,例如仅使用表示可打印 ASCII 字符的字节。 (例如,对于漏洞利用有效载荷)。

指定您希望汇编程序使用哪种形式
一些汇编器具有覆盖其默认编码选择的语法,例如GAS had a .s suffix to get the non-default encoding .现在已弃用,您应该使用 {load}{store}助记符前的前缀( see the docs ),如下所示:

{load} xor %eax, %ecx
{store} xor %eax, %ecx
{vex3} vpaddd %xmm0, %xmm1, %xmm1
vpaddd %xmm0, %xmm1, %xmm1        # default is to use 2-byte VEX when possible
gcc -c foo.S && objdump -drwC foo.o
0:   31 c1                   xor    %eax,%ecx
2:   33 c8                   xor    %eax,%ecx
4:   c4 e1 71 fe c8          vpaddd %xmm0,%xmm1,%xmm1
9:   c5 f1 fe c8             vpaddd %xmm0,%xmm1,%xmm1
(相关: What methods can be used to efficiently extend instruction length on modern x86? 用于 {vex3}{evex}{disp32} 的用例。)
NASM 还有{vex2} , {vex3} , 和 {evex}与 GAS 语法相同的前缀,例如{vex3} vpaddd xmm1, xmm1, xmm0 .但我没有看到覆盖 op r/m, r 的方法对比 op r, r/m操作码的选择。

相关问答,有些基本重复
  • Why does the Solaris assembler generate different machine code than the GNU assembler here? - 一些汇编器有不同的默认“方向”选择。
  • 一些汇编程序甚至使用该选择(可能还有其他冗余)作为在其输出机器代码中添加足迹/水印的一种方式。 Notably A86这是共享软件,使用它来检测未支付共享软件费用的人的二进制文件。 A86 tag wiki .
  • What is the ".s" suffix in x86 instructions? ({load}{store} 在 GAS 源中覆盖的前身)。
  • Encoding ADC EAX, ECX - 2 different ways to encode? (arch x86)
  • x86 sub instruction opcode confusion
  • 关于assembly - x86 XOR 操作码差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50336269/

    相关文章:

    assembly - 向BX寄存器写入值对ES寄存器有影响吗?

    assembly - 实模式中断处理例程未按预期工作

    c - 这个计划如何评价?

    c# - 了解非 bool 参数之间的按位比较

    php - 使用按位运算符的不同模块的用户角色权限

    assembly - 我试图在 AAM 指令之后使用 AX 中存储的值将其除以 2,为什么它不适用于 2 位数字输出?

    c - 将 128 位寄存器从汇编传递给 C 函数

    assembly - 了解 x86 MOV 语法

    assembly - 为什么字节码编程不如汇编编程那么流行或盛行?

    linux - 需要清理缓冲区吗? x86 Linux 汇编器