assembly - 为什么 cmp 指令中的参数顺序很重要?

标签 assembly x86 att

我想知道为什么 cmp 指令需要特定的参数顺序条件。

例如,我已经尝试过这两种方法。

  1. cmpl %eax, $'A'
  2. cmpl $'A', %eax

第一行返回错误,表示操作数类型不匹配。 第二线效果很好。

我浏览了Intel IA-32手册,但它无法回答我的问题。它只是说参数 1 和 2 之间的减法,而不是每个参数应该具有哪些类型。

我想知道为什么第一行代码返回操作数类型不匹配,但第二行却没有。

最佳答案

机器代码指令仅支持带有立即数的指示。如果您没有找到这个,那么您找错地方了。英特尔的第 2 卷手册详细介绍了每条指令的每种可用编码。 Here's an HTML extract of the entry for cmp .


请记住,程序集限制不是任意的源代码级别选择;而是任意的。它不是像 C++ 这样的语言,它是一种描述机器代码的方式。

大多数 ALU 指令都会写入其目的地(尤其是可追溯到原始 8086 的指令),因此它不可能是立即数。例如sub %eax, $123 显然没有意义。 因此,机器代码格式的一致性/易于解码是没有具有直接“目标”的特殊 cmp 操作码的原因之一。对于汇编语法来说,这也是不规则的,如果汇编器将该操作码映射到相同的 cmp 助记符,而不是不同的反向 cmp 助记符。

相比之下,cmp r/m32, r32cmp r32, r/m32 都存在,因此您可以在任一方向将内存与寄存器进行比较。同样,这与其他 ALU 指令(例如 addsub)的模式一致,因此这对于机器代码中更“常规”的解码/模式也有意义。

如果您使用 jcc 对结果进行分支,您始终可以交换操作数并使用相反的条件。有时您希望 CF 设置某种方式来提供 adcsbb,不过,是的,有时这会带来不便。

但这还不足以让 8086 指令集架构师 Stephen Morse 使用少数未使用的操作码之一与 cmp 的立即编码进行反向比较。


有意义的是像 ARM 那样的反向减法或反向比较指令(即 dst = src - dst 而不是 dst -= src),但 x86 的可变长度机器代码格式意味着只有这么多 1 字节操作码。这可能只是又一条“正常”立即 ALU 指令。

或者实际上还有 5 个操作码,包括 2 个专用字节(如果我们遵循普通 ALU 指令的模式):普通 op r/m8, imm8, op r/m16, sign_extended_imm8, op r/m16, imm16 以及 AL,imm8 和 AX,imm16 短格式(没有 ModRM 字节)。我猜想对于非立即操作数,助记符可能是 cmp 的别名,操作数相反,因此我们不需要这 4 个操作码(两个方向上的 8 位和 16 位)。

ARM 后来出现并使用固定宽度的 32 位指令字,因此有相当多的操作码编码空间可用于反向比较和反向减法等有用指令。

关于assembly - 为什么 cmp 指令中的参数顺序很重要?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56205683/

相关文章:

assembly - 请验证 AT&T Assembly line 的含义

macos - 将 JonesForth 移植到 macOS v10.15 (Catalina)

visual-c++ - 如何将汇编标记放入 C++ 代码 (x64)

qt - x86 Qt应用程序在Mac OS 10.7(Lion)上崩溃

optimization - Intel为指令添加前缀,检查优化问题

c++ - std::memory_order_XXX 是如何工作的

assembly - x86 汇编语言中的函数调用

windows - 如何在 Windows 10 专业版 64 位上将二进制文件刻录到通过软盘 USB 插入的软盘的扇区 0

无法从 MSR 读回

assembly - 将 16 位复制到内存位置