簡體   English   中英

android ndk asm編譯錯誤:'asm'中的操作數限制不一致

[英]android ndk asm compile error: inconsistent operand constraints in an 'asm'

我正在為android編譯一段asm代碼:

static void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d)
{
      __asm__ __volatile__ (
      "cpuid"
      : "=a" (*a) ,
      "=b" (*b) ,
      "=c" (*c) ,
      "=d" (*d)
      : "0" (function)) ;
}

APP_ABI設置為“all”:APP_ABI:= all

來到x86時編譯失敗:

$ ndk-build
[armeabi-v7a] Gdbserver      : [arm-linux-androideabi-4.6] libs/armeabi-v7a/gdbserver
[armeabi-v7a] Gdbsetup       : libs/armeabi-v7a/gdb.setup
[armeabi] Gdbserver      : [arm-linux-androideabi-4.6] libs/armeabi/gdbserver
[armeabi] Gdbsetup       : libs/armeabi/gdb.setup
[x86] Gdbserver      : [x86-4.6] libs/x86/gdbserver
[x86] Gdbsetup       : libs/x86/gdb.setup
[mips] Gdbserver      : [mipsel-linux-android-4.6] libs/mips/gdbserver
[mips] Gdbsetup       : libs/mips/gdb.setup
[armeabi-v7a] Compile thumb  : hello-jni <= CpuArch.c
[armeabi-v7a] SharedLibrary  : libhello-jni.so
[armeabi-v7a] Install        : libhello-jni.so => libs/armeabi-v7a/libhello-jni.so
[armeabi] Compile thumb  : hello-jni <= CpuArch.c
[armeabi] SharedLibrary  : libhello-jni.so
[armeabi] Install        : libhello-jni.so => libs/armeabi/libhello-jni.so
[x86] Compile        : hello-jni <= CpuArch.c
D:/adt/ndk/samples/hello-jni/jni/CpuArch.c: In function 'MyCPUID':
D:/adt/ndk/samples/hello-jni/jni/CpuArch.c:75:3: error: inconsistent operand constraints in an 'asm'
/cygdrive/d/adt/ndk/build/core/build-binary.mk:391: recipe for target '/cygdrive/d/adt/ndk/samples/hello-jni/obj/local/x86/objs-debug/hello-jni/CpuArch.o' failed
make: *** [/cygdrive/d/adt/ndk/samples/hello-jni/obj/local/x86/objs-debug/hello-jni/CpuArch.o] Error 1

我對asm沒有多少經驗。 並且錯誤消息似乎不足以找到解決方案。 :(

順便說一句,使用cygwin在win7中進行編譯。

完整版本:

static void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d)
{
  #ifdef USE_ASM

  #ifdef _MSC_VER

  UInt32 a2, b2, c2, d2;
  __asm xor EBX, EBX;
  __asm xor ECX, ECX;
  __asm xor EDX, EDX;
  __asm mov EAX, function;
  __asm cpuid;
  __asm mov a2, EAX;
  __asm mov b2, EBX;
  __asm mov c2, ECX;
  __asm mov d2, EDX;

  *a = a2;
  *b = b2;
  *c = c2;
  *d = d2;

  #else

  __asm__ __volatile__ (
    "cpuid"
    : "=a" (*a) ,
      "=b" (*b) ,
      "=c" (*c) ,
      "=d" (*d)
    : "0" (function)) ;

  #endif

  #else

  int CPUInfo[4];
  __cpuid(CPUInfo, function);
  *a = CPUInfo[0];
  *b = CPUInfo[1];
  *c = CPUInfo[2];
  *d = CPUInfo[3];

  #endif
}

這段代碼基於我在Stackoverflow答案中編寫的內容。 必須注意在某些基於x86的架構/ ABI上保留%ebx寄存器。 當生成位置無關代碼( -fPIC gcc選項)時, %ebx用於重定位代碼(共享對象等)。 下面的代碼避免在擴展匯編程序輸出中使用=b ,並使用編譯器知道的空閑和可用的寄存器。 通過在調用cpuid之前和之后將其交換到空閑寄存器來保留%ebx 我還修復了與%ecx寄存器相關的一個小的gotchya錯誤。 我將其清除為0( "c"(0) ),因為在某些體系結構上,如果不這樣做將導致cpuid返回過時的值。

static void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d)
{
#if defined(__i386__)
    __asm__ __volatile__ (
           "xchgl\t%%ebx, %k1\n\t"      \
           "cpuid\n\t"                  \
           "xchgl\t%%ebx, %k1\n\t"

      : "=a"(*a), "=&r"(*b), "=c"(*c), "=d"(*d)
      : "a"(function), "c"(0));

#elif defined(__x86_64__)
    __asm__ __volatile__ (
           "xchgq\t%%rbx, %q1\n\t"      \
           "cpuid\n\t"                  \
           "xchgq\t%%rbx, %q1\n\t"

      : "=a"(*a), "=&r"(*b), "=c"(*c), "=d"(*d)
      : "a"(function), "c"(0));
#else
#error "Unknown architecture."
#endif
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM