Gcc 内联程序集返回:创建共享对象时,无法使用针对未定义符号的重新定位R_X86_64_32S

Gcc 内联程序集返回:创建共享对象时,无法使用针对未定义符号的重新定位R_X86_64_32S,gcc,assembly,x86,inline-assembly,Gcc,Assembly,X86,Inline Assembly,我正在工作。他正在使用Visual Studio和英特尔汇编,内联。我已经尝试将其改编为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 re

我正在工作。他正在使用Visual Studio和英特尔汇编,内联。我已经尝试将其改编为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 = %s\n", maxBasicCPUID, vendorString);
  return 0xb45eba11;
}

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

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

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

   uint32_t *str = (uint32_t *)vendorString;
   __asm("cpuid"
       : "=a"(maxBasicCPUID), "=b"(str[0]), "=d"(str[1]), "=c"(str[2])
       : "a"(0));
第一行参数告诉编译器在哪里存储结果,第二行告诉编译器在执行内联程序集之前要加载哪些值


有关所有详细信息,请参阅。(感谢@MichaelPetch的链接。)

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

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

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

   uint32_t *str = (uint32_t *)vendorString;
   __asm("cpuid"
       : "=a"(maxBasicCPUID), "=b"(str[0]), "=d"(str[1]), "=c"(str[2])
       : "a"(0));
第一行参数告诉编译器在哪里存储结果,第二行告诉编译器在执行内联程序集之前要加载哪些值


有关所有详细信息,请参阅。(感谢@MichaelPetch提供的链接。)

使用GCC,您需要使用模板将数组和变量传递给程序集。您使用32位寄存器作为指针,但仍然为x86-64编译。但更重要的是,MSVC风格的内联asm与GNUC风格完全不同。有了GCC,您将希望使用模板将数组和变量传递给程序集。您正在使用32位寄存器作为指针,但仍在为x86-64编译。但更重要的是,MSVC风格的内联asm与GNUC风格完全不同。