使用 Nasm 汇编程序的 CMPXCHG8B 示例

CMPXCHG8B example using Nasm Assembler

谁能给我一个非常简单的例子,说明如何在 NASM 汇编程序中使用 x86 CMPXCHG8B 指令?

一切都应该通过注释、标签和代码结构来解释,只是对 lock 前缀的注释。虽然它使它成为原子,但它也变得非常慢,因为所有内核都必须在此时同步并确保内存访问没有冲突。

话又说回来,在没有 lock 的情况下,通常没有合理的理由使用类似 cmpxchg 的指令,因为并行进程的原子同步是唯一优于许多其他解决方案的用法。

对于真正简单的非原子 "exchange" 内存内容,一组经典的 mov 指令很可能胜过任何 xchg,特别是如果您提前计划交换并且 read/write 所有值都有适当的延迟,不会阻塞内存带宽访问。

如果您希望此处有一些关于并行编程同步的教程,那么只是 google 一些 book/etc,这不是 "one answer" 主题,而更像是 "one book" 主题。

section .text
    global _start       ;must be declared for using gcc
_start:                 ;tell linker entry point

    ; fail example (memory contains different than expected value)

    ; edx:eax = old value (to compare with memory)
    mov eax,'BAD '
    mov edx,'val.'
    ; ecx:ebx = new value to set
    mov ebx,'NEW '
    mov ecx,`val\n`
    ; CMPXCHG8B should fail, old value is different
    lock cmpxchg8b [value]  ; "lock" makes it atomic for multi-core
    ; here edx:eax == `OLD val\n` (the unexpected content of [value])

    call displayValue

    ; pass example (memory value as expected)

    ; edx:eax = old value (to compare with memory)
    mov eax,'OLD '
    mov edx,`val\n`
    ; ecx:ebx = new value to set
    mov ebx,'NEW '
    mov ecx,`val\n`
    ; CMPXCHG8B should pass, setting up new value
    lock cmpxchg8b [value]  ; "lock" makes it atomic for multi-core

    call displayValue

    ;system call number (sys_exit)
    mov eax, 1
    int 0x80

displayValue:
    mov edx, 8      ;message length
    mov ecx, value  ;message to write
    mov ebx, 1      ;file descriptor (stdout)
    mov eax, 4      ;system call number (sys_write)
    int 0x80        ;call kernel
    ret

section .data

value  db   `OLD val\n`     ; 8 bytes long memory

构建并 运行,将其保存为 "cmpxchg8b.asm":

nasm -f elf32 cmpxchg8b.asm
ld -m elf_i386 -s -o cmpxchg8b cmpxchg8b.o
./cmpxchg8b

预期输出(当然在 linux 框上):

$ ./cmpxchg8bdemo
OLD val                                                                  
NEW val