C:-O3 的奇怪标签行为?

C: Weird label behavior with -O3?

鉴于此代码(最小示例;其中没有更深层的含义):

#include <stdio.h>

int main() {
    start:
    asm volatile(
        ".code64\n\t"
        "push %rax\n\t"
        "pop %rax"
    );
    end:
    printf("%ld\n", (const char *)&&end - (const char *)&&start);
}

我们通过执行gcc -O3 -S dummy.c -o -得到汇编代码。可以看到,这些行包括在内:

        subq    , %rsp
        .cfi_def_cfa_offset 16
#APP
# 5 "dummy.c" 1
        .code64
        push %rax
        pop %rax
# 0 "" 2
#NO_APP
        leaq    .L2(%rip), %rax

这实际上意味着原始汇编代码仍在二进制文件中(这是预期的)。

但是如果执行程序,则输出0。这基本上意味着开始标签等于结束标签。另一方面,如果程序是用 -O0 编译的,它会输出 2.

为什么gcc -O3 dummy.c && ./a.out即使包含汇编代码也输出0?

谢谢

里面有GCC bug 40078 and in particular comment 1:

<...> labels can be moved if they are not used normally in the program. <...> Addresses of labels are only designed for computed gotos and any other use causes undefined behavior of their placement.

进一步的评论建议 asm goto GCC(从 4.5 版开始)的功能可能对记者有所帮助。

的确,asm goto可以帮助您固定标签的位置。我想 asm goto 是标签的“正常用途”之一。请参见以下示例。请注意我如何将 asm goto 用作单独的语句,因为它后面的“有用”语句有一个输出,asm goto 语句不能有。

#include <stdio.h>

int main()
{
start:
    asm goto(""::::start,end);

    unsigned random=0;
    asm volatile("rdrand %0\n" : "=r"(random));
end:
    printf("Random number: %u; label difference: %ld\n",
           random, (long)(&&end - &&start));
}

Play with it online!