我有一些简单的代码可以找出两个程序集标签之间的区别:
#include <stdio.h>
static void foo(void){
__asm__ __volatile__("_foo_start:");
printf("Hello, world.\n");
__asm__ __volatile__("_foo_end:");
}
int main(void){
extern const char foo_start[], foo_end[];
printf("foo_start: %p, foo_end: %p\n", foo_start, foo_end);
printf("Difference = 0x%tx.\n", foo_end - foo_start);
foo();
return 0;
}
现在,这段代码在 64 位处理器上完美工作,就像您期望的那样。然而,在 32 位处理器上,foo_start 的地址与 foo_end 相同。
我确定它与 32 到 64 位有关。在 i386 上,它产生 0x0,而 x86_64 产生 0x7。在 ARMv7(32 位)上,结果为 0x0,而在 ARM64 上,结果为 0xC。 (64位的结果是正确的,我用反汇编器检查过)
我正在使用 Clang+LLVM 进行编译。
我想知道它是否与非惰性指针有关。在上面提到的两个 32 位处理器 archs 的汇编输出中,它们最后都有这样的东西:
L_foo_end$non_lazy_ptr:
.indirect_symbol _foo_end
.long 0
L_foo_start$non_lazy_ptr:
.indirect_symbol _foo_start
.long 0
但是,这不出现在 x86_64 和 ARM64 的汇编输出中。我昨天搞砸了删除非惰性指针并直接处理标签,但无济于事。关于为什么会发生这种情况的任何想法?
编辑:
当为 32 位处理器编译时,foo_start[] 和 foo_end[] 似乎指向 main。我....我很困惑。
最佳答案
我没有检查真实代码,但怀疑您是指令重排序的受害者。只要您没有定义适当的内存屏障,编译器就会在函数内随意移动您的代码,因为它认为合适,因为标签和 printf() 调用之间没有相互依赖性。
尝试将 :::"memory"
添加到您的 asm 语句中,这应该将它们钉在您编写它们的位置。
关于c - 32 位处理器上的程序集标签地址不正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22733347/