c - 32 位处理器上的程序集标签地址不正确

标签 c assembly 32bit-64bit

我有一些简单的代码可以找出两个程序集标签之间的区别:

#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/

相关文章:

c - 数组的长度在传递函数后发生变化

c++ - 通过查看程序集比较按值传递与按引用传递的性能

performance - 在 x86-64 上,32 位应用程序比 64 位应用程序有性能优势吗?

c++ - 如何用c语言翻译openssl命令pbkdf2?

c - 如何在没有连接的情况下同步管理器/工作线程?

objective-c - Objective-C 程序可以编译成 int 为 64 位吗?

c++ - 有效地交织位

assembly - 3 操作数 imul 指令在 ia-32 汇编中到底起什么作用?

linux - 64 位 linux 内核如何从 ELF 启动 32 位进程

windows - 有没有人为 Windows x64 编译 PCRE - 如果是这样,怎么做?