错误:`cmpxchg'的指令后缀无效

时间:2013-03-12 23:00:34

标签: c++ assembly x86-64

我正在尝试编译另一个项目的代码,并且我继续获取Error: invalid instruction suffix for 'cmpxchg'。错误指向的代码行是:

inline bool CAS(long *ptr, long oldv, long newv) {
  unsigned char ret;
  /* Note that sete sets a 'byte' not the word */
  __asm__ __volatile__ (
                "  lock\n"
                "  cmpxchgq %2,%1\n"
                "  sete %0\n"
                : "=q" (ret), "=m" (*ptr)
                : "r" (newv), "m" (*ptr), "a" (oldv)
                : "memory");
  return ret;
}

我想知道是否有人知道错误的原因是什么,可能的解决方案是什么?

1 个答案:

答案 0 :(得分:2)

正如评论家所说,问题是cmpxchg末尾的'q'。汇编器使用指令后缀字符来指示位宽,否则它将是不明确的。

对于64位目标,此代码使用gcc编译正常。你得到cmpxchgq指令的输出。

f0 48 0f b1 16          lock cmpxchg %rdx,(%rsi)

f0是LOCK前缀,48是REX.W前缀。真正的操作码是0f b1。

编译32位目标(gcc选项-m32)会导致后缀错误。

如果您需要此代码在32位计算机上运行,​​那么您在此处遇到了移植问题。 sizeof(long)在64位机器上为8,在32位机器上为4。 IF 并且它是一个很大的if,整个程序具有足够的弹性以容忍从8到4个字节的“长”,只需将'q'后缀更改为'l'即可逃脱(这是一个小写的L)。这为您提供了32位格式的'0f b1'指令:

 f0 0f b1 16             lock cmpxchg %edx,(%esi) 

如果没有,那么您可以尝试重写32位目标的程序集以使用CMPXCHG8B,这是一个具有不同寄存器触摸行为的不同指令。 CMPXCHG8B不是直接替代品!