下面的atomic64_read代码在x86环境中工作,但对x64失败。
asm volatile(
"mov %%ebx, %%eax\n"
"mov %%ecx, %%edx\n"
"lock cmpxchg8b %1\n"
: "=&A" (ret)
: "m" (v->counter64)
);
有趣的是,锁定操作是指x86中的寄存器'ecx'(:edx),但在x64中它指的是'rax'寄存器。
lock cmpxchg8b (%ecx)
=> 86
lock cmpxchg8b (%rax)
=> 64
我还尝试转换上面给出的代码,考虑到rax和rcx是64位寄存器。它正确地将值移动到rax寄存器,但在lock语句中给出了段错误。
asm volatile(
"mov %%rcx, %%rax\n"
"lock cmpxchg8b %1\n"
: "=&A" (ret)
: "m" (v->counter64)
);
答案 0 :(得分:1)
原始版本失败,因为“A”约束表示rax / eax / ax / al和/或rdx / edx / dx / dl,而x64 rdx仅为结果分配,因此mov指令会覆盖地址RAX。
你可以将结果分成两半:
uint32_t lo, hi;
asm volatile(
"mov %%ebx, %%eax\n"
"mov %%ecx, %%edx\n"
"lock cmpxchg8b %2\n"
: "=&a" (lo), "=&d" (hi)
: "m" (v->counter64)
);
ret = lo | ((uint64_t)hi << 32);
然而,普通阅读是否足够?
ret = *(volatile uint64_t)&v->counter64
或者内存排序不足?