Android arm汇编程序中的迭代数组

Android arm汇编程序中的迭代数组,android,assembly,java-native-interface,arm,Android,Assembly,Java Native Interface,Arm,我想在Android的ARMAssembly中迭代数组,但我得到了致命的信号错误和应用程序崩溃 我会展示里面的东西 首先,我使用jni从java访问c代码: 我声明了本机函数: public native byte[] BitmapToGrayscale(byte[] bitmap); private void ConvertImageToGrayscale() { if(image == null) { GetLenaBack(); info

我想在Android的ARMAssembly中迭代数组,但我得到了致命的信号错误和应用程序崩溃

我会展示里面的东西

首先,我使用jni从java访问c代码:

我声明了本机函数:

public native byte[] BitmapToGrayscale(byte[] bitmap);
 private void ConvertImageToGrayscale()
{
    if(image == null)
    {
        GetLenaBack();
        info("Nie było obrazu, ustawiono domyślny.");
    }

    ByteBuffer bb = ByteBuffer.allocate(image.getByteCount());
    image.copyPixelsToBuffer(bb);
    info("Start");
    ByteBuffer result = ByteBuffer.wrap(this.BitmapToGrayscale(bb.array()));
    info("Stop");
    image.copyPixelsFromBuffer(result);
    display.setImageBitmap(image);
}
之后,我通过调用以下函数调用代码:

public native byte[] BitmapToGrayscale(byte[] bitmap);
 private void ConvertImageToGrayscale()
{
    if(image == null)
    {
        GetLenaBack();
        info("Nie było obrazu, ustawiono domyślny.");
    }

    ByteBuffer bb = ByteBuffer.allocate(image.getByteCount());
    image.copyPixelsToBuffer(bb);
    info("Start");
    ByteBuffer result = ByteBuffer.wrap(this.BitmapToGrayscale(bb.array()));
    info("Stop");
    image.copyPixelsFromBuffer(result);
    display.setImageBitmap(image);
}
C中的函数如下所示:

JNIEXPORT jbyteArray JNICALL Java_pl_marekbar_Main_BitmapToGrayscale
(JNIEnv * env, jobject thisObj, jbyteArray bitmap)
{
    jbyte arraySize = (*env)->GetArrayLength(env, bitmap);
    jbyte *arrayAddress = (*env)->GetByteArrayElements(env, bitmap, 0);
    jbyte cellSize = sizeof((*env)->GetByteArrayElements(env, bitmap, 0));

    Grayscale(arrayAddress, arraySize, cellSize);
    return bitmap;
}
最后,这是我的asm代码:

@ This file is jni/Grayscale.s
    .text
    .align  2
    .global Grayscale
    .type   Grayscale, %function
Grayscale:
@Convert to grayscale
    stmfd   sp!, {fp,ip,lr}
@r0 - pointer
@r1 - array length
@r2 - array element size
    mov r3, #0 @current element
array_loop:
    ldr r4, [r0] @load element to memory


    str r4, [r0] @store element in memory
    add r0, r0, r4 @move pointer
    add r3, r3, #1 @increment index

    cmp r3, r1 @compare current index with array length
    bne array_loop @when index smaller than array length still iterate


    ldmfd   sp!, {fp,ip,lr}
    bx  lr
    .size   Grayscale, .-Grayscale

我需要了解如何正确使用arm asm中c代码传递的数组。我不想在C中这样做,因为我正在为图像处理准备应用程序,必须快速。

您的
arraySize
cellSize
组合看起来不正确:

jbyte arraySize = (*env)->GetArrayLength(env, bitmap);
jbyte cellSize = sizeof((*env)->GetByteArrayElements(env, bitmap, 0));
  • jbyte
    是一种
    int8\u t
    (即有符号8位类型)。因此,
    arraySize
    可能无法容纳数组的实际长度,除非图像非常小

  • 您正在将
    cellSize
    设置为
    jbyte*
    的大小,很可能是4个字节。这恰好对应于32位ARGB像素的大小,但它仍然不是确定每个像素大小的正确方法。这些信息应该作为另一个参数从Java代码传递到C代码

  • 由于汇编代码迭代
    arraySize
    次,它将尝试读取
    arraySize
    单词(即
    arraySize*4
    字节)。但是您的数组只包含
    arraySize
    字节


  • 您在汇编代码中对数组指针使用了错误的增量:

    ldr r4, [r0] @load element to memory
    add r0, r0, r4 @move pointer
    

    添加到指针的是刚刚从数组中读取的像素数据。就像@Masta79注释的那样,您可能想要的是将
    r2
    (元素大小)添加到指针。

    您以一种非常奇怪的方式移动指针(将它增加到刚刚从数组加载的32位值)。您确定这是正确的吗?在不深入研究的情况下,您的汇编代码使用r4而不将其保存到堆栈中。只有r0-r3、ip和lr可以在不保存的情况下进行修改。只需使用r3而不是r4,并递减r1,直到其达到0,即可在阵列上循环。这至少可以阻止它崩溃。但它本身的代码看起来并不是很有效。正如Michael所指出的,你可能想用r2而不是r4来增加r0。还有,
    cellSize
    应该是什么?每像素的字节数?从外观上看,您将其设置为指针大小,至少为4个字节。我认为该像素由4个字节组成-ARGB pixel-png image。我想让整个像素进行注册,然后再进行操作。你们不应该为了图像处理而费心使用ARM组件。你肯定应该选择霓虹灯,因为它对这种工作来说速度非常快,而且比你说的ARMI更容易编程。我将数组长度和像素大小从java传递到C,然后传递到asm。我现在可以把像素读入寄存器,用零清除它,然后保存。我不知道该如何从寄存器中将像素分割成若干部分。ldr命令将32位加载到寄存器-整个像素。我想我必须使用一些遮罩,对吗?要将ARGB转换为灰度,我会使用类似
    ((R*0.299+G*0.587+B*0.114)*A)/256的东西