代码之家  ›  专栏  ›  技术社区  ›  Pindatjuh

x86 CMP指令差异

  •  12
  • Pindatjuh  · 技术社区  · 14 年前

    问题

    以下两条x86指令之间的(非平凡的)区别是什么?

    39 /r    CMP r/m32,r32   Compare r32 with r/m32
    3B /r    CMP r32,r/m32   Compare r/m32 with r32
    

    背景

    我正在构建一个Java汇编程序,它将被编译器的中间语言用来生成Windows 32可执行文件。

    目前我有以下代码:

    final ModelBase mb = new ModelBase(); // create new memory model
    mb.addCode(new Compare(Register.ECX, Register.EAX)); // add code
    mb.addCode(new Compare(Register.EAX, Register.ECX)); // add code
    
    final FileOutputStream fos = new FileOutputStream(new File("test.exe"));
    mb.writeToFile(fos);
    fos.close();
    

    输出一个有效的可执行文件,该文件在一个文本节中包含两条CMP指令。输出到“text.exe”的可执行文件没有什么有趣的,但这不是重点。班级 Compare 是一个包裹 CMP 指示。

    以上代码生成(使用ollydbg检查):

    Address   Hex dump                 Command
    0040101F  |.  3BC8                 CMP ECX,EAX
    00401021  |.  3BC1                 CMP EAX,ECX
    

    区别很微妙:如果我使用 39 字节操作码:

    Address   Hex dump                 Command
    0040101F  |.  39C1                 CMP ECX,EAX
    00401021  |.  39C8                 CMP EAX,ECX
    

    这让我想知道他们的同义词,为什么这甚至存在。

    3 回复  |  直到 11 年前
        1
  •  18
  •   interjay    14 年前

    如果比较两个寄存器,使用哪种操作码并不重要。唯一的区别是当比较寄存器和内存操作数时,因为使用的操作码决定从中减去哪个。

    至于存在的原因:x86指令格式使用modr/m字节来表示内存地址或寄存器。每条指令只能有一个modr/m值,这意味着它只能访问一个内存地址(不包括像movsb这样的特殊指令)。所以这意味着不可能有一个将军 cmp r/m32, r/m32 指令,我们需要两个不同的操作码: cmp r/m32, r32 cmp r32, r/m32 . 作为副作用,这在比较两个寄存器时会产生一些冗余。

        2
  •  3
  •   phuclv    11 年前

    它是 redundancy of x86 . 像这样的案例多得多。编译器/汇编程序可以自由使用任何有效的操作码

    一些汇编程序允许您选择要发出的操作码。例如,在gas上可以附加“.s”以使用其他指令编码

    10 de   adcb   %bl,%dh
    12 f3   adcb.s %bl,%dh
    
        3
  •  2
  •   Jens Björnhager    14 年前

    cmp-ecx,eax是ecx-eax,cmp-eax,ecx是eax-ecx。根据与哪个操作数进行比较,标志的设置有所不同。当然,如果不是因为x86指令的mod/r-m结构,您可能只需要使用其中一个就可以了。