Android arm汇编程序中的迭代数组
我想在Android的ARMAssembly中迭代数组,但我得到了致命的信号错误和应用程序崩溃 我会展示里面的东西 首先,我使用jni从java访问c代码: 我声明了本机函数: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
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的东西