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

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

#include <stdio.h>

unsigned char mema[4] = {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和其他事物所需的特权级别,我只对链接错误感兴趣,为什么链接错误在一个系统/编译器而不是另一个系统/编译器上起作用。

henshui22 回答:某些内联汇编程序出现一两个奇怪的链接错误

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

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

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

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

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

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

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

本文链接:https://www.f2er.com/3073072.html

大家都在问