内联程序集返回:创建共享对象时不能使用针对未定义符号的重定位R_X86_64_32S



我正在研究中间装配幻灯片 18 中 Xeno Kovah 的示例。他正在使用带有Intel Assembly的Visual Studios,内联。我尝试将其改编为 GCC,如下所示。我正在编译-masm=intel -fPIC

#include <stdio.h>
int main(){
unsigned int maxBasicCPUID;
char vendorString[13];
char * vendorStringPtr = (char *)vendorString; //Move the address into its own register
//because it makes the asm syntax easier
//First we will check whether we can even use CPUID
//Such a check is actually more complicated than it seems (OMITED FROM SLIDES)
__asm (
"mov edi, vendorStringPtr;" //Get the base address of the char[] into a register
"mov eax, 0;" //We're going to do CPUID with input of 0
"cpuid;" //As stated, the instruction doesn't have any operands
//Get back the results which are now stored in eax, ebx, ecx, edx
//and will have values as specified by the manual
"mov maxBasicCPUID, eax;"
"mov [edi], ebx;" //We order which register we put into which address
"mov [edi+4], edx;" //so that they all end up forming a human readable string
"mov [edi+8], ecx;"
);
vendorString[12] = 0;
printf("maxBasicCPUID = %#x, vendorString = %sn", maxBasicCPUID, vendorString);
return 0xb45eba11;
}

我不确定我做错了什么,但我收到以下错误

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

在 gcc 中,您不能在汇编代码中直接按名称引用局部变量。

此外,您需要告诉编译器您使用的所有寄存器(clobber)。

但是,从好的方面来说,你可以让编译器为你做更多的工作,正如你在下面的代码重写中看到的那样:

uint32_t *str = (uint32_t *)vendorString;
__asm("cpuid"
: "=a"(maxBasicCPUID), "=b"(str[0]), "=d"(str[1]), "=c"(str[2])
: "a"(0));

第一行参数告诉编译器将结果存储在何处,第二行告诉编译器在执行内联程序集之前要加载哪些值。

有关所有详细信息,请参阅 https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html。 (感谢@MichaelPetch的链接。

最新更新