【问题标题】:What is the semantics of testb $1, %altestb $1, %al 的语义是什么
【发布时间】:2018-05-02 12:49:20
【问题描述】:

我正在尝试了解这条 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

【问题讨论】:

  • boperand-size 是 byte,而不是 bit,所以 $1 是一个只设置了低位的字节。奇怪的是,clang 使用单独的加载而不是带有内存操作数的 test;该函数不再使用该值,因此无需将其保存在寄存器中。或者实际上,英特尔上的immediate + RIP-relative wouldn't micro-fuse。它也可能无法进行宏融合,因此您最终可能会在英特尔上从test $1, _flag_atomic(%rip) / jnz 获得 3 个融合域微指令。
  • 请注意,movb 已经是一个微融合负载 + 合并到 RAX 的低字节,但 on recent Intelmovzbl 会避免错误的依赖。所以 clang 已经有 3 个未融合域的 uops(其中 2 个来自 movb),但这种方式总共只有 2 个融合域的 uops。
  • 是的,由于某种原因,这只发生在 atomic_load 上,因为标量负载 clang 会在不使用 %al 的情况下生成 cmpb
  • 啊,是的,atomic 在编译器中得到了特殊处理,并且(如volatile)有时会结束优化器。当前的编译器甚至没有优化重复的原子负载,尽管当前的标准确实允许这样做:Can and does the compiler optimize out two atomic loads?,尤其是我对Why don't compilers merge redundant std::atomic writes?的回答
  • 感谢分享资源。很有用!我经常使用godbolt顺便说一句。 PS:gcc.gnu.org/bugzilla/show_bug.cgi?id=85610

标签: c++ assembly x86 clang x86-64


【解决方案1】:

在 AT&T 语法中,$ 是立即值的前缀 (see also); $1 是一个普通的 1,因此您的指令根据 al 的最低有效位设置标志。

是全 1 (0xFF) 还是单个 1 (0x1)?

所有的都是

testb $-1, %al

或(完全相同的机器代码,只是反汇编偏好)

testb $0xff, %al

顺便说一句,它的语义与

完全相同
testb %al, %al

(作为0xff 8 位寄存器的掩码不会屏蔽任何内容),在这种情况下也适用于您的代码,因为对于布尔值,不需要屏蔽任何内容以检查是否这是真的(而且 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;

jnejnz 的别名,在这种情况下可能更清楚)。

【讨论】:

    【解决方案2】:

    0x 以十六进制数字为前缀。 0 以八进制数为前缀,如果您未提及任何前缀,它将是十进制数系统。在您的情况下,这是十进制数字系统中的 1。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-02
      相关资源
      最近更新 更多