在 ASM 中为 cmpxchg16b 设置寄存器

Setting up registers for cmpxchg16b in ASM

我正在尝试使用 lock cmpxchg16b 指令在 C 语言的外部函数中进行原子比较和交换。 该函数的调用有 3 128 位对象,我想比较其中的前 2 个,如果它们相等,则替换为第三个。

这些是我收集的参数:

rdi:旧状态

rsi:当前状态

rdx: mod 状态

现在,我要做的是将 rdi(不应该有后半部分吗?)加载到 rax 中,并将此状态的后半部分加载到 rdx 中。 (rdi+8??)

如果我在那里做的是正确的,那么在做的时候 rdx 将与 rsi 和 rax 与 rsi+8 进行比较

lock cmpxchg16b (%rsi)

对吧?因为它是小端

但是如何将 rdi 移动到 rdx:rax? 我试过这个:

movq (%rdi), %rdx

movq %rdi, %rdx

但我似乎无法让它工作,它总是喷出它们不相等,即使 运行 它与同一个对象两次。

现在功能齐全:

my_cmpr_swap:
    #save rbx as we need the register
    pushq %rbx
    # set up registers rdx:rax
    movq %rdx, (%rdi)
    #compare-swap
    lock cmpxchg16b (%rsi)

    #return 1 if success, 0 if not
    jz success
    movq [=13=],%rax
    jmp end
success:
    movq ,%rax
end:
    popq %rbx
    ret

此答案假定您通过引用传递旧值和新值。

my_cmpr_swap:
    #save rbx as we need the register
    pushq %rbx

    # set up registers rcx:rbx
    movq (%rdx), %rbx
    movq 8(%rdx), %rcx

    # set up registers rdx:rax
    movq (%rdi), %rax
    movq 8(%rdi), %rdx

    #compare-swap
    lock cmpxchg16b (%rsi)

    #return 1 if success, 0 if not
    jz success

    # store updated rdx:rax
    movq %rax, (%rdi)
    movq %rdx, 8(%rdi)

    movq [=10=],%rax
    jmp end
success:
    movq ,%rax
end:
    popq %rbx
    ret

此答案假定您按值传递旧值和新值。

my_cmpr_swap:
    #save rbx as we need the register
    pushq %rbx

    mov %rdx, %r10

    # set up registers rcx:rbx
    movq %rcx, %rbx
    movq %r8, %rcx

    # set up registers rdx:rax
    movq %rdi, %rax
    movq %rsi, %rdx

    #compare-swap
    lock cmpxchg16b (%r10)

    #return 1 if success, 0 if not
    jz success

    movq [=10=],%rax
    jmp end
success:
    movq ,%rax
end:
    popq %rbx
    ret