1

我正在尝试编译另一个项目的代码,并且一直在获取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;
}

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

4

1 回答 1

2

正如评论员所提到的,问题在于 cmpxchg 末尾的“q”。汇编器使用指令后缀字符来指示位宽,否则它会不明确。

此代码可以使用 gcc 编译为 64 位目标。您将获得 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,在 Linux 的 32 位机器上为 4。 如果,如果整个程序有足够的弹性来容忍从 8 到 4 个字节的“长”,那么您可以通过将“q”后缀更改为“l”(这是一个小写 L )。这为您提供了 32 位形式的 '0f b1' 指令:

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

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

于 2013-03-13T00:15:26.943 回答