某些内联汇编出现一个或两个奇怪的链接错误

问题描述 投票:1回答:1

我有以下简短的应用程序(原文取自:https://www.aldeid.com/wiki/X86-assembly/Instructions/str。我刚刚对其进行了修改(尝试...),使其也可以在linux上编译。

#include <stdio.h>

unsigned char mema[4] = {0, 0, 0, 0};

void test4 (void)
{

    asm (
        "str mema\n"
    );

    printf ("\n[+] Test 4: STR\n");
    printf ("STR base: 0x%02x%02x%02x%02x\n", mema[0], mema[1], mema[2], mema[3]);

    if ((mema[0] == 0x00) && (mema[1] == 0x40))
        printf ("Result  : VMware detected\n\n");
    else
        printf ("Result  : Native OS\n\n");
}

int main () {

    test4();
}

以及当我尝试编译它时:

$ gcc -ggdb -O0 -fPIC -x c ./pill.c -o pill                                                                                                       

它给了我奇怪的错误:

/usr/bin/ld: /tmp/ccDhGo05.o: relocation R_X86_64_32S against symbol `mema' can not be used when making a PIE object; recompile with -fPIC
/usr/bin/ld: final link failed: Nonrepresentable section on output
collect2: error: ld returned 1 exit status

然而,同样的事情在在线编译器上也起作用:https://gcc.godbolt.org/z/RYWjy8

...,除非当我抱怨变量mema在函数test4的两个地方时都将其作为局部变量

undefined symbol `mema' 

还有另一个怪异:用clang编译时,相同的东西也可以工作。

知道为什么会这样吗? (不考虑STR和其他事物所需的特权级别,我仅对链接错误以及为什么它在一个系统/编译器而不是另一个系统/编译器上起作用感到兴趣。

c gcc hyperlink clang linker-errors
1个回答
2
投票

[当您编写asm("str mema\n");时,编译器实际上将str mema写入汇编文件。

在用-fPIC编译的程序中,汇编代码不允许包含程序中任何内容的任何地址(这是与位置无关的means)。因此,不允许您使用包含全局变量mema的地址的指令。

局部变量不是汇编器一开始就知道的东西。

如果要用汇编指令读取或写入变量,则需要告诉编译器您要读取或写入的内容,然后让编译器找出要写入的确切代码:

asm("str %0" : "=m" (mema));

["=m"说该值是一个输出(=),它必须是一个存储位置(m),但是编译器会弄清楚实际位置应该是什么。

[The GCC manual has more information(叮当声的工作方式相同)。

© www.soinside.com 2019 - 2024. All rights reserved.