gcc - 64 位整数的 cmpxchg 示例

标签 gcc assembly x86-64 inline-assembly

我在 i686 架构中使用 cmpxchg(比较和交换)进行 32 位比较和交换,如下所示。

(编者注:最初的 32 位示例有问题,但问题不在于它。我相信这个版本是安全的,作为奖励,它也可以为 x86-64 正确编译。 另请注意内联 asm不需要或不建议这样做; __atomic_compare_exchange_n 或更旧的 __sync_bool_compare_and_swapint32_tint64_t 在 i486 和 x86-64 上工作。但这个问题是关于使用内联 asm 进行的你还想。)

// note that this function doesn't return the updated oldVal
static int CAS(int *ptr, int oldVal, int newVal)
{
    unsigned char ret;
    __asm__ __volatile__ (
            "  lock\n"
            "  cmpxchgl %[newval], %[mem]\n"
            "  sete %0\n"
            : "=q" (ret), [mem] "+m" (*ptr), "+a" (oldVal)
            : [newval]"r" (newVal)
            : "memory");    // barrier for compiler reordering around this

    return ret;   // ZF result, 1 on success else 0
}

64 位比较和交换的 x86_64 架构的等效项是什么
static int CAS(long *ptr, long oldVal, long newVal)
{
    unsigned char ret;
    // ?
    return ret;
}

最佳答案

x86_64指令集有 cmpxchgq ( q 对于四字)8 字节(64 位)比较和交换指令。

还有一个cmpxchg8b适用于 8 字节数量的指令,但设置起来更复杂,需要您使用 edx:eaxecx:ebx而不是更自然的 64 位 rax .这种情况存在的原因几乎可以肯定与英特尔早在 x86_64 之前就需要 64 位比较和交换操作有关。伴随着。它仍然以 64 位模式存在,但不再是唯一的选择。

但是,如前所述,cmpxchgq可能是 64 位代码的更好选择。

如果需要 cmpxchg 一个 16 字节的对象,cmpxchg8b 的 64 位版本是 cmpxchg16b .它在最早的 AMD64 CPU 中没有,所以编译器不会为 std::atomic::compare_exchange 生成它。在 16B 对象上,除非您启用 -mcx16 (对于 gcc)。不过,汇编器会对其进行组装,但请注意,您的二进制文件不会在最早的 K8 CPU 上运行。 (这仅适用于 cmpxchg16b ,不适用于 64 位模式下的 cmpxchg8bcmpxchgq )。

关于gcc - 64 位整数的 cmpxchg 示例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/833122/

相关文章:

c - 我怎样才能 LD_PRELOAD 我自己编译的库?

linux - "Unexplainable"核心转储

matplotlib - .plt .plt.got 有什么不同?

c - 如何在 makefile 中包含 *.so 文件

java - 使用 gcc 创建共享库

assembly - 确保跳转的字母数字 Shellcode

linux - 为什么我们不能使用 esp 寄存器直接引用内存地址?

algorithm - 如何打印二叉搜索树?

macos - 如何在 ARM M1 Apple Silicon Mac 上将 Rust 代码交叉编译为 Intel 程序集?

c - 我应该如何为 gcc 的 -nostartfiles 或 -nostdlib 选项编写代码?