x86 CMP 指令差异

发布于 2024-08-31 04:08:37 字数 1181 浏览 7 评论 0原文

问题

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

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

Question

What is the (non-trivial) difference between the following two x86 instructions?

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

Background

I'm building a Java assembler, which will be used by my compiler's intermediate language to produce Windows-32 executables.

Currently I have following code:

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();

To output a valid executable file, which contains two CMP instruction in a TEXT-section. The executable outputted to "text.exe" will do nothing interesting, but that's not the point. The class Compare is a wrapper around the CMP instruction.

The above code produces (inspecting with OllyDbg):

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

The difference is subtle: if I use the 39 byte-opcode:

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

Which makes me wonder about their synonymity and why this even exists.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

打小就很酷 2024-09-07 04:08:37

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

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

It doesn't matter which opcode you use if you compare two registers. The only difference is when comparing a register with a memory operand, as the opcode used determines which will be subtracted from which.

As for why this exists: The x86 instruction format uses the ModR/M byte to denote either a memory address or a register. Each instruction can only have one ModR/M value, which means it can only access one memory address (not including special instructions like MOVSB). So this means that there can't be a general cmp r/m32, r/m32 instruction, and we need two different opcodes: cmp r/m32, r32 and cmp r32, r/m32. As a side effect, this creates some redundancy when comparing two registers.

御守 2024-09-07 04:08:37

这是x86 的冗余。类似这样的案例还有很多。编译器/汇编器可以自由使用任何有效的操作码。

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

10 de   adcb   %bl,%dh
12 f3   adcb.s %bl,%dh

It's redundancy of x86. There are much more many cases like this. A compiler/assembler is free to use any of the valid opcodes

Some assembler allows you to choose which opcode to emit. For example on GAS you can attach ".s" to use the other instruction encoding

10 de   adcb   %bl,%dh
12 f3   adcb.s %bl,%dh
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文