【问题标题】:Why is order of arguments in cmp instruction important?为什么 cmp 指令中的参数顺序很重要?
【发布时间】:2019-05-19 07:34:56
【问题描述】:

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

例如,这两种我都试过了。

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

第一行返回错误,说操作数类型不匹配。 第二行运行良好。

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

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

【问题讨论】:

  • 英特尔手册明确指出,第一个操作数必须是寄存器或内存操作数。由于您使用的是 AT&T 语法,因此操作数以相反的顺序给出,$'A' 既不是寄存器也不是内存操作数。

标签: assembly x86 att


【解决方案1】:

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


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

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

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

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

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


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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-03-10
    • 2020-11-22
    • 1970-01-01
    • 2022-01-06
    • 2021-03-26
    • 2013-05-18
    • 1970-01-01
    相关资源
    最近更新 更多