【问题标题】:ASM: operand type mismatch for `cmp'ASM:“cmp”的操作数类型不匹配
【发布时间】:2023-03-27 10:12:01
【问题描述】:

我正在编写 x86 汇编代码,但一直收到此错误:`cmp's 的操作数类型不匹配

它出现的代码行是:

cmpb %rdi, $0

【问题讨论】:

  • 因为这似乎是 AT&T 语法代码,所以直接操作数应该在左边。
  • @DavidWohlferd:立即数可能是一个字节。 CMP r/m64, imm8CMP r/m64, imm32 都有,所以你需要一种方法来消除两者之间的歧义。
  • @Michael 大小后缀不表示立即数的大小,而是表示操作的大小。

标签: assembly x86


【解决方案1】:

在 AT&T 语法(这是您使用的)中,指令有一个 size 后缀 来指示操作数的大小。大小后缀为:

b byte        1 bytes
w word        2 bytes
l long        4 bytes
q quad-word   8 bytes

s single      4 bytes
d double      8 bytes
t temporary  10 bytes

例如,cmpb 是指令 cmp,指示的操作数大小为 1 字节。但是,您的代码使用 %rdi 作为操作数,它是一个四字(64 位)寄存器,因此汇编程序正确地抱怨这是错误的操作数。

要解决此问题,只需省略大小后缀即可;除非所有操作数都是立即数或内存操作数,否则汇编器能够推断出它:

cmp %rdi, $0

您当然也可以显式提供大小后缀;在这种情况下,q 是合适的,如上表所示:

cmpq %rdi, $0

也就是说,请注意,与大多数指令一样,立即操作数必须是 cmpq 的第一个操作数:

cmpq $0, %rdi

另一种形式实际上是非法的。

【讨论】:

  • t 通常表示十字节,而不是临时的。
  • @MichaelPetch 这是一种 retcon; fstpt 在 8087 数据表中明确称为“浮点存储临时”。
  • 当涉及到汇编程序本身时,m80fp 通常被标识为 TWORD/TBYTE(取决于您是否来自 MASM 世界)并且汇编程序不会将 TBYTE/TWORD 标识为“暂时的”。 T 表示十字节(80 位)操作数。AT&T 语法中的t 后缀以相同的容量运行。
  • cmp %rdi, $0 仍然是非法的:x86 只允许 cmp felixcloutier.com/x86/CMP.html 的直接右侧(Intel 语法),因此 AT&T 中只允许使用 cmp $0, %rdi。如果要在相反方向进行比较,则需要寄存器中的常数。 (对于0 无关紧要,无论如何都应该使用test %rdi,%rdi;两个方向都不能进位或溢出,因此您始终可以使用相反的条件,例如 jge 而不是 jl)
  • @PeterCordes 已解决。
猜你喜欢
  • 2015-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-08
相关资源
最近更新 更多