最近在我的大学开始了 ARM 汇编课程,或者任务是创建一个从 C 代码调用的 NxM * MxP 矩阵乘法程序。
现在我在 assambler 方面的知识相当有限,但我非常愿意学习。我想知道的是:
- 如何从 C 读取/传递 2D 数组到 ASM?
- 如何将二维数组输出回C?
我在想,我可以自己解决剩下的问题,但是这两点是我觉得困难的。
我在 qemu 上使用 ARM 程序集,在 Ubuntu 上使用此代码,它不会在任何特定设备上运行。
C 数组只是指针,因此当您将 C 数组作为参数传递给 assemply 函数时,您将获得一个指向内存区域的指针,该指针是数组的内容。
对于检索参数,这取决于您使用的调用约定。ARM EABI规定:
前四个寄存器 r0-r3 (a1-a4) 用于将参数值传递给子程序并从函数返回结果值。它们也可用于在例程中保存中间值(但通常仅在子例程调用之间)。
对于简单的函数,您应该根据您的函数签名在 r0 到 r4 中找到指向数组的指针。否则,您将在堆栈中找到它。准确找出 ABI 是什么的一个好方法是反汇编调用您的汇编函数的 C 代码的目标文件,并在调用您的汇编函数之前检查它的作用。
例如,在 Linux 上,您可以在名为 的文件中编译以下 C 代码testasm.c
:
extern int myasmfunc(int *);
static int array[] = { 0, 1, 2 };
int mycfunc()
{
return myasmfunc(array);
}
然后编译它:
arm-linux-gnueabi-gcc -c testasm.c
最后得到一个反汇编:
arm-linux-gnueabi-objdump -S testasm.o
结果是:
testasm.o: file format elf32-littlearm
Disassembly of section .text:
00000000 <mycfunc>:
0: e92d4800 push {fp, lr}
4: e28db004 add fp, sp, #4
8: e59f000c ldr r0, [pc, #12] ; 1c <mycfunc+0x1c>
c: ebfffffe bl 0 <myasmfunc>
10: e1a03000 mov r3, r0
14: e1a00003 mov r0, r3
18: e8bd8800 pop {fp, pc}
1c: 00000000 andeq r0, r0, r0
可以看到,单参数函数myasmfunc
是通过将参数放入 register 来调用的r0
。的意思ldr r0, [pc, #12]
是“加载到r0
所在的内存地址的内容pc+12
”。那是存储指向数组的指针的地方。
尽管 Guillaumes 的回答对我有很大帮助,但我只是想用一些代码来回答我自己的问题。
我最终做的是创建一个一维数组,并将其与维度一起传递给 asm。
int *p;
scanf("%d", &h1);
scanf("%d", &w1);
int* A =(int *) malloc (sizeof(int) * ( w1 * h1 ));
p=A;
int i;
int j;
for(i=0;i<(w1*h1);i++)
{
scanf("%d", p++);
}
话虽如此,我以相同的 ( malloc
) 方式分配了另一个数组,并将其传递给了它。然后我只是将我需要的 int 值存储在汇编代码中的适当地址中,并且由于数组元素的地址不会改变,我只是使用相同的数组来输出结果。