2015-08-28 92 views
3

我編譯一塊彙編代碼的Android不一致操作數約束:機器人NDK ASM編譯錯誤:在 '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被設定爲 '全部': APP_ABI:=所有

$ 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多少經驗:

在編譯時來的x86失敗。而錯誤味精似乎不足以找到解決方案。 :(

BTW,編譯是在Win7使用的cygwin取得

完整版:。

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 
} 
+0

這段代碼是你寫的嗎?還是它是ndk樣本的一部分?我最好的猜測是編譯器使用'-fPIC' gcc選項生成PIC代碼(位置獨立代碼)。你會看到這個錯誤,因爲'%ebx'寄存器被用作輸出寄存器 –

回答

1

這個代碼是基於一些東西我在這個Stackoverflow answer寫一個人一定要注意保護%ebx寄存器在某些基於x86的架構/ ABI上%ebx用於在生成位置獨立代碼(-fPIC gcc選項)時重新定位代碼(共享對象等)下面的代碼避免在擴展彙編器輸出中使用=b,並使用寄存器合作mpiler知道是免費且可用的。在致電cpuid之前和之後,將%ebx交換到免費註冊表。我還修復了與%ecx寄存器相關的小錯誤。我將它清除爲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 
} 
+0

謝謝你參加討論。我沒有寫代碼。它是7zip的一部分。我將它移植到Android。完整版本現在添加。我想我需要添加一些ifdef來整合你的代碼。 – gzyuan888

+0

@ gzyuan888嘗試用我的代碼替換掉'__asm__ __volatile__'的代碼(只刪除我發佈的函數聲明)。我個人認爲這是android示例代碼中的一個缺陷。我的代碼也應該可以用於64位和32位x86編譯(理論上) –