一切都应该用cmets、标签和代码结构来解释,只是注意lock前缀。虽然它是原子的,但它也很慢,因为所有内核都必须在此时同步并确保内存访问没有冲突。
再说一次,通常没有合理的理由在没有lock 的情况下使用类似cmpxchg 的指令,因为并行进程的原子同步是唯一优于许多其他解决方案的用法。
对于内存内容的真正简单的非原子“交换”,一组经典的 mov 指令很可能会胜过任何 xchg,尤其是如果您计划提前交换并以适当的延迟读取/写入所有值以不阻塞内存带宽访问。
如果您希望这里有一些关于并行编程同步的教程,那么只需谷歌搜索一些书籍/等,这不是“一个答案”主题,而更像是“一本书”主题。
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