如何在Android中使用汇编语言
我用的是Android4.0的最新开发工具,NDK是最新支持4.0的。这个NDK和旧版本有一些明显的不同。
因为我用的是Mac OS X,它比个人电脑上的配置要容易得多。你不需要安装任何杂项第三方工具,所以你可以直接使用你下载的NDK。
首先,设置目标路径——在你的终端中输入NDK的根目录,然后键入NDK _项目_路径= " "。输入并输入导出NDK项目路径。
进入汽车。
这里注意,NDK _项目_路径=后面的路径需要引号,否则无效。
由于默认情况下NDK支持的默认编译选项仅支持ARMv5至ARMv5TE架构,因此有两种方法可以使用更高级的功能:
1,你有办法把TARGET_ARCH_ABI的值改成armeabi-v7a。我自己试过,但是没用。所以可以用第二种方法,更简单方便:
2.在您的NDK目录中,找到toolchains,然后找到ARM-Linux-Android ABI-x.y.z目录,在那里您可以找到setup.mk文件。Find -march=armv7-a,去掉上面所有的#ifdef和下面的#endif。这样可以确保编译器使用ARMv7A进行编译。
完成上述操作后,我们就可以用最简单的方式编写程序集了,即内联汇编-
静态int my_thumb(int dummy)
{
__asm__("movw r0,#1001 \t\n "
movw r12,#2020 \t\n
添加r0,r0,r12 \t\n
" bx lr ");
返回虚拟对象;
}
jstring
Java _ com _ example _ hello JNI _ hello JNI _ stringFromJNI(JNIEnv * env,
jobject thiz)
{
my _ thumb(0);
return(* env)-& gt;NewStringUTF(env,“你好,来自JNI!”);
}
上面的代码实际上是基于NDK附带的hello-jni项目修改的。最后可以用ndk-build编译成功。
上面的代码是编译器默认使用Thumb/Thumb-2编译的,所以我写的所有内联汇编的指令都是Thumb代码。
我们将讨论如何使用ARM代码和使用NEON指令集。
首先在你的Android.mk中修改LOCAL_SRC_FILES,在源文件名后面加上一个. neon后缀,比如把LOCAL_SRC_FILES := hello-jni.c改为LOCAL _ SRC _ FILES:= hello-JNI . c . neon。
这里需要注意的是,不需要修改自己的真实源文件名,只需要修改符号LOCAL_SRC_FILES的值即可。
然后我们添加一个新的变量来指示ARM GCC用ARM指令集编译——local _ ARM _ mode:= ARM。
没关系。让我们修改代码:
静态int my_arm(int dummy)
{
__asm__("movw r0,#1001 \t\n "
movw r12,#2020 \t\n
添加r0,r0,r12 \t\n
vdup.32 q0,r0 \t\n
" bx lr ");
返回虚拟对象;
}
jstring
Java _ com _ example _ hello JNI _ hello JNI _ stringFromJNI(JNIEnv * env,
jobject thiz)
{
my _ arm(0);
return(* env)-& gt;NewStringUTF(env,“你好,来自JNI!”);
}
使用ndk-build后,可以正常通过编译。
最后去顶顶。直接编写程序集文件。NDK有气体工具,所以编写汇编文件是合理的。通常,程序集文件的后缀是。所以我们可以创建一个xxx.s文件。
然后我在这里创造了一个名字叫hey.s。在Android.mk中添加这个文件:local _ src _ files+= hey.s.neon。
我们在这里看到,为了在汇编文件中使用NEON指令集,我们还添加了。霓虹后缀在这里。汇编程序的Makefile也能识别这个标志。
我们编辑hey.s文件:
。文本
。对齐4
。手臂
。环球我的真实手臂
我的真实手臂:
添加r0,r0,#256
vmov q0,q1
vdup.32 q0,r0
bx lr
这里需要注意的是,在苹果的汇编程序中,函数名要有前缀和下划线,而NDK提供的汇编程序没有。
让我们修改hello-jni.c并把这个函数放入:
extern void my _ real _ arm(int I);
静态int my_arm(int dummy)
{
__asm__("movw r0,#1001 \t\n "
movw r12,#2020 \t\n
添加r0,r0,r12 \t\n
vdup.32 q0,r0 \t\n
" bx lr ");
返回虚拟对象;
}
jstring
Java _ com _ example _ hello JNI _ hello JNI _ stringFromJNI(JNIEnv * env,
jobject thiz)
{
my _ real _ arm(0);
my _ arm(0);
return(* env)-& gt;NewStringUTF(env,“你好,来自JNI!”);
}
当然,为了保证编译器能够正确混合ARM和Thumb指令集,我们可以在刚才setup.mk中的TARGET_CFLAGS标志中强制添加-mthumb-interwork。
在Windows操作系统中测试后,最终发现只要去掉Application.mk中APP_ABI中的标志,只留下armeabi-V7A,就可以流畅使用neon。这样就不需要修改setup.mk,也不需要去掉Sample中的标志判断,非常方便。
以下是可用的Android.mk编译配置文件列表:
LOCAL_PATH := $(调用my-dir)
包括美元(VARS结算)
LOCAL_MODULE := HelloNeon
LOCAL_SRC_FILES := helloneon.c
本地_ ARM _模式:= arm
TARGET _ CFLAGS+=-m thumb-interwork
TARGET _ CFLAGS+=-STD = GNU 11
TARGET_CFLAGS += -O3
ifeq ($(目标_拱门_ABI),armeabi-v7a)
LOCAL _ CFLAGS:=-d have _ NEON = 1
LOCAL _ SRC _ FILES+= neontest . s . neon
LOCAL_ARM_NEON := true
endif
LOCAL_LDLIBS := -llog
包含$(BUILD_SHARED_LIBRARY)
$(调用导入模块,CPU功能)
当使用jni时,您只需要将JNI文件夹添加到您当前的项目目录中,然后按照示例中提供的文件布局进行操作。用ndk-build编译时(Windows下cygwin控制台使用ndk-build.cmd),如果构建成功,在libs文件夹中会生成一个libXXX.so。然后用Eclipse ADT重新打开您的项目,您会发现jni文件目录和生成的so文件会显示在您的项目文件目录中。当然,您也可以编辑。的汇编文件直接放在Eclipse IDE下,这样更容易阅读。
最后,如果你想在Android汇编程序中注释一个语句,你必须在C89/90-/*中使用注释字符...*/
C++98后面引入的分号和//形式都没用。
在最新的NDK版本android-ndk-r8d中,加入了ARM-Linux GCC4.7和目前流行的LLVM Clang3.1。但是LLVM Clang3.1的很多编译选项与GCC不同,所以使用Clang3.1时需要自己配置相应的编译选项。这个版本的NDK的默认编译器工具链是GCC 4.6版。如果要使用GCC4.7,可以在Application.mk文件中添加NDK _工具链_版本= 4.7;如果要使用Clang3.1,可以在Application.mk中添加ndk _ toolkit _ version = clang 3.1以下是一个合法的Application.mk的内容:
#用LLVM构建Clang3.1
# NDK _工具链_版本= 3.1
#使用ARM-Linux GCC4.7构建
NDK工具链版本=4.7
#只构建ARMv7-A机器码。
APP_ABI := armeabi-v7a
参考上面的Douding.com。
南京宝云安卓培训班正在火热报名中~