2015-08-28 91 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编译(理论上) –