Janis Peisenieks
Janis Peisenieks

Reputation: 4988

matrix multiplication in ARM assembly

A course of ARM assembly recently started at my university, and or assignment is to create an NxM * MxP matrix multiplication programm, that is called from C code.

Now I have a fairly limited knowledge in assambler, but i'm more than willing to learn. What I would like to know is this:

  1. How to read/pass 2D arrays from C to ASM?
  2. How to output a 2D array back to C?

I'm thinking, that i can figure the rest of this out by myself, but these 2 points are what I find difficult.

I am using ARM assembly on qemu, on Ubuntu for this code, it's not going on any particular device.

Upvotes: 0

Views: 5600

Answers (2)

Janis Peisenieks
Janis Peisenieks

Reputation: 4988

Even though Guillaumes answer helped me A LOT, I just thought to answer my own question with a bit of code.

What I ended up doing was creating an a 1D array, and passing it to asm along with the dimensions.

    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++);
    }

That being said, I allocated another array the same (malloc) way, and passed it along aswell. I then just stored the int value I needed in the appropriate address in the assembly code, and since the addresses of the array elements don't change, I just used the same array to output the result.

Upvotes: 0

Guillaume Ballet
Guillaume Ballet

Reputation: 311

C arrays are merely just pointers, so when you pass a C array as an argument to an assemply function, you will get a pointer to an area of memory that is the content of the array.

For retrieving the argument, it depends on what calling convention you use. The ARM EABI stipulates that:

The first four registers r0-r3 (a1-a4) are used to pass argument values into a subroutine and to return a result value from a function. They may also be used to hold intermediate values within a routine (but, in general, only between subroutine calls).

For simple functions, them, you should find the pointer to your array in r0 to r4 depending on your function signature. Otherwise, you will find it on the stack. A good technique to find out exactly what the ABI is would be to disassemble the object file of the C code that calls your assembly function and check what it does prior to calling your Assembly function.

For instance, on Linux, you can compile the following C code in a file called testasm.c:

extern int myasmfunc(int *);

static int array[] = { 0, 1, 2 };

int mycfunc()
{
    return myasmfunc(array);
}

Then compile it with:

arm-linux-gnueabi-gcc -c testasm.c

And finally get a disassembly with:

arm-linux-gnueabi-objdump -S testasm.o

The result is:

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

You can see that the single-parametered function myasmfunc is called by putting the parameter into register r0. The meaning of ldr r0, [pc, #12] is "load into r0 the content of the memory address that is at pc+12". That is where the pointer to the array is stored.

Upvotes: 2

Related Questions