【问题标题】:Error compiling in Assembly Code for cmpxchg16b在 cmpxchg16b 的汇编代码中编译错误
【发布时间】:2013-09-21 15:28:37
【问题描述】:

我正在处理一个需要双宽度比较和交换操作 (cmpxchg16b) 的项目。我通过luke h 找到了以下代码,但是当我使用“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 共享内存。

代码:

#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 );
}

【问题讨论】:

  • 应该只是 lock cmpxchg16b %1 。在这种情况下,不需要大小,因为指令 cmpxchg16b 暗示了它。无论您在哪里获得此代码,似乎都是由认为内联汇编程序等同于 MASM 的人编写的。
  • 我可以为不使用内联汇编做一个宣传吗?使用__sync_bool_compare_and_swap 怎么样?甚至可能是 std::atomic?
  • @DavidWohlferd 哦,现在来吧,内在函数太简单了,但话说回来,您可能希望您在 GCC 上的 wiki 条目能够发挥作用;-)
  • 我偶然发现了另一个问题/答案,这似乎是此代码的起源。 stackoverflow.com/questions/4825400/cmpxchg16b-correct
  • @MichaelPetch - 嘿,我为那个 wiki 条目出汗。当然,你和我可能是唯一读过它的人,但仍然...... Re 4825400:在接受的答案中也没有内存破坏。虽然我看到您添加了评论,但您没有提及。值得为这个 5 岁以上的问题争论不休吗?

标签: c++ inline-assembly


【解决方案1】:

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

【讨论】:

  • 我的组装经验非常有限,你能举个例子吗?
  • 在这种情况下,clobber 列表中的 "memory" 不是必需的,因为更改的内存被明确列为输出操作数"+m" ( *src )
  • @MichaelPetch 我不确定我是否同意。虽然 cmpxchg16b 的正确功能可能不是必需的,但通常这种类型的语句用于同步线程。在这种情况下,您可能确实希望在执行 asm 之前将所有内容刷新到内存中。
  • @DavidWohlferd 实际上这是一个很好的观点,哈哈。在您可能使用它的情况下,我没有考虑围绕指令本身的要求。我确实同意
  • 我会保留评论,尽管它可能不准确。这一系列 cmets 可能对未来快速了解它的读者有用; ) 虽然也许有更多牛肉的答案可能是合适的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-21
  • 1970-01-01
  • 1970-01-01
  • 2016-05-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多