简体   繁体   English

如何在 Android 项目中使用 ARM 汇编代码?

[英]How to use ARM Assembly code in an Android project?

I'm not particularly experienced with Assembly and ARM, but I was able to write a few routines in it and I'd like to see how they run on an ARM-equipped Android device (Nexus S).我对组装和 ARM 并不是特别有经验,但我能够在其中编写一些例程,我想看看它们如何在配备 ARM 的 Android 设备 (Nexus S) 上运行。 What is the procedure for including an Assembly code file into an Android project?将汇编代码文件包含到 Android 项目中的过程是什么? Can I only call it from native code, or from Java also?我只能从本机代码调用它,还是从 Java 调用它?

You can call assembly from Android using the Java Native Interface and the Android NDK.您可以使用 Java 本机接口和 Android NDK 从 Android 调用程序集。

Cedric mentions using the asm keyword, while I prefer to include assembly source code. Cedric 提到使用asm关键字,而我更喜欢包含汇编源代码。 I have posted a tutorial to do this at my site: http://www.eggwall.com/2011/09/android-arm-assembly-calling-assembly.html我已经在我的网站上发布了一个教程: http://www.eggwall.com/2011/09/android-arm-assembly-calling-assembly.html

You can download the source code for my example and see how it works.您可以下载我的示例的源代码,看看它是如何工作的。 Once you see a functioning example, it is easy to modify it to your needs.一旦你看到一个运行良好的例子,就很容易根据你的需要对其进行修改。

Minimal example with inline and separate source file内联和单独源文件的最小示例

Some care has to be taken to not compile the raw assembly under the wrong arch.必须注意不要在错误的拱门下编译原始程序集。 Here we use:这里我们使用:

  • #ifdef s on C files #ifdef在 C 文件上
  • ifeq s on Android.mkAndroid.mk上的ifeq

This example on GitHub . 这个例子在 GitHub 上 Tested on Ubuntu 16.04, Android NDK 12, Sony Xperia Z3 D6643 (ARMv7) with Android 5.1.1.在 Ubuntu 16.04、Android NDK 12、Sony Xperia Z3 D6643 (ARMv7) 和 ZE84E30B9390CDB64DB6DB52C9AB87846DK 12 上进行了测试。

jni/main.c jni/main.c

#include <stdio.h>

#include <jni.h>

#ifdef __arm__
int asm_main(void);
#endif

jstring Java_com_cirosantilli_android_1cheat_ndk_1asm_Main_jniMethod(
        JNIEnv* env, jobject thiz) {
    enum Constexpr { N = 256 };
    char s[N];
    size_t cur = 0;

    int x = 0;
#ifdef __arm__
    cur += snprintf(s + cur, N - cur, "arm ");
    /* Inline test. Increment x by 1. */
    asm (
        "add %0, #1"
        : "=r" (x)
        : "0" (x)
    );
    /* Separate source test. Increment x by 1. */
    x += asm_main();
#endif
    if (x == 2)
        cur += snprintf(s + cur, N - cur, "%s", "0");
    else
        cur += snprintf(s + cur, N - cur, "%s", "1");

    return (*env)->NewStringUTF(env, s);
}

jni/main_asm.S jni/main_asm.S

.text
/* Function that just returns 1. */
.global asm_main
asm_main:
    mov r0, #1
    bx lr

jni/Android.mk jni/Android.mk

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := main
LOCAL_SRC_FILES := main.c
# http://stackoverflow.com/questions/12614417/android-ndk-how-to-get-compiler-architecture-in-android-mk-dynamically
ifneq (,$(filter $(TARGET_ARCH_ABI),armeabi armeabi-v7a))
    LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) main_asm.S
endif
include $(BUILD_SHARED_LIBRARY)

com/cirosantilli/android_cheat/ndk_asm/Main.java com/cirosantilli/android_cheat/ndk_asm/Main.java

package com.cirosantilli.android_cheat.ndk_asm;

import android.app.Activity;
import android.widget.TextView;
import android.os.Bundle;

public class Main extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        TextView tv = new TextView(this);
        tv.setText(jniMethod());
        setContentView(tv);
    }
    public native String jniMethod();
    static {
        System.loadLibrary("main");
    }
}

I think this should be possible when using the NDK that allows you to write C/C++ code packaged in a.apk and then run on the android platform.我认为当使用允许您编写打包在 a.apk 中的 C/C++ 代码然后在 android 平台上运行的NDK时,这应该是可能的。

With this, you will be able to use the __asm__ keyword in your C code (as mentionned in the release notes of the Revision 5b).这样,您将能够在 C 代码中使用__asm__关键字(如修订版 5b 的发行说明中所述)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM