0

最近在我的大学开始了 ARM 汇编课程,或者任务是创建一个从 C 代码调用的 NxM * MxP 矩阵乘法程序。

现在我在 assambler 方面的知识相当有限,但我非常愿意学习。我想知道的是:

  1. 如何从 C 读取/传递 2D 数组到 ASM?
  2. 如何将二维数组输出回C?

我在想,我可以自己解决剩下的问题,但是这两点是我觉得困难的。

我在 qemu 上使用 ARM 程序集,在 Ubuntu 上使用此代码,它不会在任何特定设备上运行。

4

2 回答 2

2

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”。那是存储指向数组的指针的地方。

于 2013-05-19T09:17:09.790 回答
0

尽管 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 值存储在汇编代码中的适当地址中,并且由于数组元素的地址不会改变,我只是使用相同的数组来输出结果。

于 2013-06-10T05:43:15.853 回答