给定此代码(最小的示例;其中没有更深层次的含义):
#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 $8, %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?
谢谢
发布于 2020-07-06 13:55:47
如果程序中没有正常使用<...>标签,则可以移动它们。标签的<...>地址只为计算的gotos和任何其他用途而设计,导致它们的放置行为不明确。
还有一条评论认为GCC的asm goto功能(自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));
}https://stackoverflow.com/questions/62755027
复制相似问题