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」です。アセンブラは、命令サフィックス文字を使用して、ビット幅があいまいな場合にビット幅を示します。

このコードは、64ビットターゲットのgccで正常にコンパイルされます。cmpxchgq命令に対してこの出力を取得します。

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

そのf0はLOCKプレフィックスであり、48はREX.Wプレフィックスです。実際のオペコードは0fb1です。

32ビットターゲット(gccオプション-m32)用にコンパイルすると、サフィックスエラーが発生します。

このコードを32ビットマシンで動作させる必要がある場合は、ここで移植の問題が発生します。Linuxの場合、sizeof(long)は64ビットマシンでは8、32ビットマシンでは4です。 プログラム全体が8バイトから4バイトまでの「長い」を許容するのに十分な弾力性がある場合は、「q」サフィックスを「l」(小文字のL)に変更するだけで問題を解決できます。 )。これにより、「0fb1」命令が32ビット形式で提供されます。

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

そうでない場合は、32ビットターゲットのアセンブリを書き直して、レジスタのタッチ動作が異なる別の命令であるCMPXCHG8Bを使用することができます。CMPXCHG8Bはドロップイン代替品ではありません!

于 2013-03-13T00:15:26.943 に答える