【发布时间】:2020-10-26 12:24:06
【问题描述】:
鉴于此代码(最小示例;其中没有更深层次的含义):
#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?
谢谢
【问题讨论】:
-
谢谢:)!这似乎是正确的答案!
-
这真的可以编译吗?使用
&&(双元地址运算符)合法吗?获取运算符结果的地址是什么意思?没有对象可以取地址?!? -
这是一个 GNU C 扩展:gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html
-
@Ruslan 请考虑将此作为答案发布。
-
为什么是疯狂的 asm 模板字符串?如果还没有,你切换到 64 位代码生成,破坏 32 位构建。然后你通过使用堆栈指令来保存/恢复 RAX 来破坏 RSP 下面的红色区域。 (Using base pointer register in C++ inline asm)。如果您只想要虚拟填充物,
nop将是显而易见的选择。或者lock addb $0, (%rsp)是其他对架构状态没有影响的东西,您可以在没有任何clobber声明的情况下使用它。
标签: c gcc optimization inline-assembly goto