assembly - x86 CMP 指令差异

标签 assembly x86 instruction-set cmp

问题

以下两条 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();

输出一个有效的可执行文件,该文件的TEXT部分包含两条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

这让我想知道它们的同义词以及为什么它存在。

最佳答案

如果比较两个寄存器,使用哪个操作码并不重要。唯一的区别是在将寄存器与内存操作数进行比较时,因为所使用的操作码决定了将从哪个操作数中减去哪个操作数。

至于为什么会存在这种情况:x86 指令格式使用 ModR/M 字节来表示内存地址或寄存器。每条指令只能有一个ModR/M值,即只能访问一个内存地址(不包括MOVSB等特殊指令)。所以这意味着不能有通用的cmp r/m32, r/m32指令,我们需要两个不同的操作码:cmp r/m32, r32cmp r32,r/m32。作为副作用,这会在比较两个寄存器时产生一些冗余。

关于assembly - x86 CMP 指令差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2760794/

相关文章:

assembly - 在汇编中隔离整数乘法中的数字?

assembly - 尝试获取内存访问模式统计信息时如何处理虚拟地址?

c# - 当安装为 Windows 服务时,我的 x86 Exe 以 x64 运行

java - Java 是否在可用时使用 AES-NI?

c++ - 在 C++ 中,使用 std::min 或 if 分支来限制值是否更好?

gcc - 如何限制 GCC 中的自动矢量化级别?

assembly - 如何在 Linux 驱动程序中切换到实模式

c - 如何从 C/汇编中的内存地址执行函数?

assembly - 在 Cortex-M0 中模拟 LDREX/STREX(加载/存储独占)

linux - 有没有办法在没有底层操作系统的情况下驱动当今的计算机 NIC?