我试图理解这个testb指令(x86-64)会做什么。
testb $1, %al
这里$ 1的价值是多少?它是所有的(0xFF
)还是单一的1(0x1
)?
该程序集由clang生成,用于以下程序:
#include <atomic>
std::atomic<bool> flag_atomic{false};
extern void f1();
extern void f2();
void foo() {
bool b = flag_atomic.load(std::memory_order_relaxed);
if (b == false) {
f1();
} else {
f2();
}
}
与(clang ++ -s test.cpp -O3)相关的程序集如下:
Lcfi2:
.cfi_def_cfa_register %rbp
movb _flag_atomic(%rip), %al
testb $1, %al ; <<<<------------
jne LBB0_2
在AT&T语法中,$
是立即值的前缀(see also); $1
是一个普通的1,所以你的指令根据al
的最低位来设置标志。
是全部(0xFF)还是单个1(0x1)?
所有人都会
testb $-1, %al
或(完全相同的机器代码,只是反汇编偏好)
testb $0xff, %al
顺便说一句,它的语义与语法完全相同
testb %al, %al
(作为8位寄存器上的0xff
的掩码不会掩盖任何东西),并且在这种情况下对于你的代码也是有效的,对于布尔值,应该不需要掩盖任何东西以检查它是否为真(并且确实gcc更喜欢你的代码的最后一个版本)。
movb _flag_atomic(%rip), %al
testb $1, %al
jne LBB0_2
在Intel语法中(没有前缀,没有后缀,dest, source
操作数顺序,显式内存寻址语法)这是
mov al, [rip+_flag_atomic]
test al, 1
jne LBB0_2
并且,在伪C中:
%al = _flag_atomic;
if(%al & 1 != 0) goto LBB0_2;
(jne
是jnz
的别名,在这种情况下可能更清楚)。
0x
以十六进制数为前缀。 0
以八进制数为前缀,如果您没有提到任何前缀,则它将是十进制数字系统。在您的情况下,这是十进制数字系统中的1。