如何在Android中使用組合語言

來源:互聯網
上載者:User

由於Android環境非常複雜,架構都是用Java,因此要使用C/C++都需要做很多配置,使用彙編的話需要做更多的工作。

我這邊使用的是最新的Android4.0的開發工具,NDK也是最新支援4.0的。這個NDK與老版本的有一些比較明顯的不同。

由於我用的是Mac OS X,因此配置起來比瘟抖死上的要容易許多,你不需要再裝些雜七雜八的第三方工具,直接可以使用你下載好的NDK。

首先,設定目標路徑——在你的Terminal中進入NDK的根目錄,隨後打NDK_PROJECT_PATH="<你要編譯的項目路徑>"。斷行符號,再輸入export NDK_PROJECT_PATH

斷行符號。

這裡要注意的是NDK_PROJECT_PATH=後面的路徑需要加引號,否則無效。

由於NDK預設支援的預設編譯選項僅支援ARMv5到ARMv5TE架構,因此如果要使用比較進階的特性的話有兩種方法:

1、你有辦法將TARGET_ARCH_ABI的值變為armeabi-v7a,俺自己試了一下,木有成功。因此可以使用第二種方法,更簡單便捷:

2、在你的NDK目錄下,找到toolchains,然後找到arm-linux-androideabi-x.y.z目錄,在進去可以發現setup.mk檔案。找到-march=armv7-a,將上面的神馬#ifdef都去掉,下面的#endif也都刪了。這樣就能確保編譯器使用ARMv7A來編譯。

完成上述操作之後我們就可以先用最簡單的方式來寫彙編了,即內聯彙編——

static int my_thumb(int dummy){    __asm__("movw r0, #1001 \t\n"            "movw r12, #2020 \t\n"            "add r0, r0, r12 \t\n"            "bx  lr");        return dummy;}jstringJava_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,                                                  jobject thiz ){    my_thumb(0);    return (*env)->NewStringUTF(env, "Hello from 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

這樣就OK了。我們修改一下代碼:

static int my_arm(int dummy){    __asm__("movw r0, #1001 \t\n"            "movw r12, #2020 \t\n"            "add r0, r0, r12 \t\n"            "vdup.32 q0, r0 \t\n"            "bx  lr");        return dummy;}jstringJava_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,                                                  jobject thiz ){    my_arm(0);    return (*env)->NewStringUTF(env, "Hello from JNI !");}

 使用ndk-build後能正常通過編譯。

最後再上個最最高端的。直接寫彙編檔案。NDK帶有GAS工具,因此按常理,完全可以寫彙編檔案。一般彙編檔案的尾碼名為.s,因此我們建立一個xxx.s檔案即可。

然後我這邊建立一個叫hey.s。在Android.mk中將這個檔案添加上:LOCAL_SRC_FILES += hey.s.neon

我們這裡看到,為了能在彙編檔案中使用NEON指令集,我們在這裡也把.neon尾碼添加上。彙編器的makefile也認這個標識。

我們編輯hey.s檔案:

.text
.align 4
.arm

.globl my_real_arm


my_real_arm:

add r0, r0, #256
vmov q0, q1
vdup.32 q0, r0

bx lr

這裡要注意的是,在Apple的彙編器中,函數名要加首碼底線,而NDK中提供的彙編器則不需要。

我們修改一下hello-jni.c,把這函數調進去:

extern void my_real_arm(int i); static int my_arm(int dummy){    __asm__("movw r0, #1001 \t\n"            "movw r12, #2020 \t\n"            "add r0, r0, r12 \t\n"            "vdup.32 q0, r0 \t\n"            "bx  lr");        return dummy;}jstringJava_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,                                                  jobject thiz ){    my_real_arm(0);    my_arm(0);    return (*env)->NewStringUTF(env, "Hello from JNI !");}

 

當然,我們為了確保編譯器能夠正確地將ARM和Thumb指令集做混合串連,我們可以在剛才的setup.mk中強制在TARGET_CFLAGS標誌裡加上-mthumb-interwork

在Windows作業系統中實驗,終於發現,只要將Application.mk中的APP_ABI中的標誌,將armeabi去掉,僅留下armeabi-v7a就能順利使用neon了。這樣不需要修改setup.mk,也不需要將Sample中的那個標誌判斷去掉,非常方便。

下面列一下可用的Android.mk編譯設定檔:

LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE := HelloNeonLOCAL_SRC_FILES := helloneon.cLOCAL_ARM_MODE := armTARGET_CFLAGS += -mthumb-interworkTARGET_CFLAGS += -std=gnu11TARGET_CFLAGS += -O3ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)LOCAL_CFLAGS := -DHAVE_NEON=1LOCAL_SRC_FILES += neontest.s.neonLOCAL_ARM_NEON  := trueendifLOCAL_LDLIBS := -lloginclude $(BUILD_SHARED_LIBRARY)$(call import-module,cpufeatures)

在使用JNI時,只需要在你當前項目工程目錄中添加jni檔案夾,然後在裡面根據Sample中所提供的檔案布局來做即可。當你用ndk-build(Windows下要在cygwin控制台中用ndk-build.cmd)來編譯時間, 如果構建成功,則會在libs檔案夾內產生一個libXXX.so。然後用Eclipse ADT重新開啟你的項目工程,就會發現jni檔案目錄以及產生好的so檔案都會在你的工程檔案目錄中展現出來。當然,你後面也能直接在Eclipse IDE下編輯.s彙編檔案,這樣就更容易閱讀了。

最後,在Android彙編器中如果要注釋某條語句,那麼必須使用C89/90中的注釋符——/* ... */

用分號以及後來C++98中所引入的//形式都不管用。

在最新的NDK版本android-ndk-r8d中加入了ARM-Linux GCC4.7以及當前大紅大紫的LLVM Clang3.1。不過由於LLVM Clang3.1的很多編譯選項與GCC有不少區別,因此在使用Clang3.1的時候需要自己去配置相應的編譯選項。這個版本的NDK預設的編譯器工具鏈使用的是GCC4.6版本。如果要使用GCC4.7,那麼可以在Application.mk檔案中添加NDK_TOOLCHAIN_VERSION=4.7;如果要使用Clang3.1,那麼可以在Application.mk中添加NDK_TOOLCHAIN_VERSION=clang3.1。下面給出一個合法的Application.mk的內容:

# Build with LLVM Clang3.1#NDK_TOOLCHAIN_VERSION=clang3.1# Build with ARM-Linux GCC4.7NDK_TOOLCHAIN_VERSION=4.7# Build only ARMv7-A machine code.APP_ABI := armeabi-v7a

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.