C++ 编译cmpxchg16b的汇编代码时出错

C++ 编译cmpxchg16b的汇编代码时出错,c++,inline-assembly,C++,Inline Assembly,我正在从事一个需要双宽度比较和交换操作(cmpxchg16b)的项目。我通过找到以下代码,但是,当我使用“g++-4.7-g-DDEBUG=1-std=c++0x-dwcas2.c-o dwcas2.o”编译它时,我得到以下错误: 错误: g++-4.7 -g -DDEBUG=1 -m64 -std=c++0x dwcas2.c -o dwcas2.o dwcas2.c: Assembler messages: dwcas2.c:29: Error: junk `ptr ' after expr

我正在从事一个需要双宽度比较和交换操作(cmpxchg16b)的项目。我通过找到以下代码,但是,当我使用“g++-4.7-g-DDEBUG=1-std=c++0x-dwcas2.c-o dwcas2.o”编译它时,我得到以下错误:

错误:

g++-4.7 -g -DDEBUG=1 -m64 -std=c++0x dwcas2.c -o dwcas2.o
dwcas2.c: Assembler messages:
dwcas2.c:29: Error: junk `ptr ' after expression
你知道为什么吗?我觉得它很小,很容易修复,我就是看不见

计算机规格: 运行Ubuntu 12.04 LTS的64核ThinkMate RAX QS5-4410服务器。它是一个NUMA系统,有四个AMD Opteron 6272 CPU(每片芯片16个核@2.1 GHz)和314 GB共享内存

代码:

#包括
命名空间类型
{
结构uint128\u t
{
uint64_t lo;
uint64_t hi;
}
__属性_uuu((uuu对齐_uuu(16));
}
模板内联bool cas(volatile T*src、tcmp、T with);
模板内联布尔cas(易失性类型::uint128\u t*src,类型::uint128\u t cmp,类型::uint128\u t with)
{
布尔结果;
__asm\uuuuuuuuuuuuuuuuuu挥发性__
(
“锁定cmpxchg16b oword ptr%1\n\t”
“设置为%0”
:“=q”(结果)
,“+m”(*src)
“+d”(cmp.hi)
,“+a”(cmp.lo)
:“c”(with.hi)
,“b”(带lo)
:“抄送”
);
返回结果;
}
int main()
{
使用名称空间类型;
uint128_t检验={0xdecafbad,0xfeedbeef};
uint128\u t cmp=测试;
uint128_t with={0x555555,0xaaaaaa};
返回!cas(&测试,cmp,带);
}

在x86 GCC上默认使用AT&T语法汇编,但您的源代码是英特尔语法。您可能还需要在clobber列表中使用“内存”。

我在汇编方面的经验非常有限,您能提供一个示例吗?在这种情况下,clobber列表中的“内存”是不必要的,因为更改的内存被显式列为输出操作数
“+m”(*src)
@MichaelPetch我不确定是否同意。虽然cmpxchg16b的正确功能可能不需要它,但通常这种类型的语句用于同步线程。在这种情况下,您可能确实希望在执行asm之前将所有内容刷新到内存中。@DavidWohlferd实际上这是一个非常好的观点。lol。在您可能使用它的情况下,我没有考虑指令本身的要求。我确实同意,我会保留评论,尽管它可能不准确。这一行评论可能对未来的读者很有用,他们会很快加以掩饰;)虽然可能一个带有更多beefin的答案是合适的。它应该是
锁cmpxchg16b%1
。本例中的大小不需要,因为它由指令
cmpxchg16b
暗示。似乎无论你在哪里得到的这段代码都是由一个认为内联汇编程序等同于MASM的人编写的。我能为不使用内联asm做一点宣传吗?使用如何?或者甚至可能是std::atomic?@DavidWohlferd哦,来吧,内部函数太简单了,但是你可能希望你在GCC上的wiki条目有价值;-)我偶然发现了另一个问题/答案,它似乎是这段代码的起源@MichaelPetch-嘿,我被维基条目弄得汗流浃背。当然你和我可能是唯一读过这本书的人,但是。。。Re 4825400:在接受的答案中也没有内存缓冲区。虽然我看到你添加了一条评论,但你没有提到这一点。在这个5年多的老问题上争论是否值得?
#include <stdint.h>

namespace types
{
    struct uint128_t
    {
        uint64_t lo;
        uint64_t hi;
    }
    __attribute__ (( __aligned__( 16 ) ));
}

template< class T > inline bool cas( volatile T * src, T cmp, T with );

template<> inline bool cas( volatile types::uint128_t * src, types::uint128_t cmp, types::uint128_t with )
{
    bool result;
    __asm__ __volatile__
    (
        "lock cmpxchg16b oword ptr %1\n\t"
        "setz %0"
        : "=q" ( result )
        , "+m" ( *src )
        , "+d" ( cmp.hi )
        , "+a" ( cmp.lo )
        : "c" ( with.hi )
        , "b" ( with.lo )
        : "cc"
    );
    return result;
}

int main()
{
    using namespace types;
    uint128_t test = { 0xdecafbad, 0xfeedbeef };
    uint128_t cmp = test;
    uint128_t with = { 0x55555555, 0xaaaaaaaa };
    return ! cas( & test, cmp, with );
}