Search code examples
cassemblygame-boy-advance

ARM Assembly - Adding two Registers


I'm trying to add two registers together in ARM Assembly, by dereferencing the first two registers, and then storing the result in the third register.

At the moment I have 3 variables & a function, which are as follows;

extern void my_function(int* x, int* y, int* total);

int main(void){
   int x = 1;     //R0
   int y = 2;     //R1
   int total = 0; //R2

   while(1){
      my_function(&x, &y, &total);
      printf("\x1b[5;5HTotal = %d, total");
   }
}

And a function this does the following

With the first two registers, I'm trying to dereference them, add them together and store the result in a third register. This is my assembly code;

ldr r4, [r0]    @ Dereference r0, and store the address in R4
ldr r4, [r1]    @ Dereference r1, and store the address in R4
add r2, r0, r1  @ Add r0 & r1 together, and store in R2
str r4, [r2]    @ Store r2 address in r4

When I print this out, the answer is 0. My question is, when I do the first two lines in assembly, does ldr r4, [r0] get replaced with ldr r4, [r1] which is causing the output to be 0? Do they each need to be stored in their own register? Or am I just basically printing out the total (r2)?


Solution

  • Never start an assembly language project without the documentation. Then actually read that documentation.

    You have a C compiler so you can just see what it does and then figure out what each instruction is doing and then figure out where you went wrong.

    void my_function(int* x, int* y, int* total)
    {
        *total = *x + *y;
    }
    

    can produce depending on command line options

    my_function:
        ldr r3, [r0]
        ldr r1, [r1]
        add r3, r3, r1
        str r3, [r2]
        bx  lr
    

    you also have to understand the calling convention for the compiler you are using to make the C/asm transition. for this case in arm r0 is the address of x, r1 the address of y, and r2 the address of total.

    ldr r4, [r0]    @ read the value of x into r4
    ldr r4, [r1]    @ read the value of y into r4 losing/discarding the value of x
    add r2, r0, r1  @ add the pointers together destroying the pointer to total
    str r4, [r2]    @ store the value of y into a location destroying whatever was there
    

    per the typical calling convention (a compiler can choose to use/create whatever they want so you need to know the convention) for arm r4 is volatile so you need to push it on the stack, you cant destroy what is in it during your function.

    because your program does not modify the total variable and it is part of .bss the bootstrap has zeroed total to zero, and you are simply printing out that value, that is why you see zero your code has nothing to do with it. The odds of the address of x plus the address of y being the address of total is very very small, basically zero (yet a program could be crafted where it works), so again your code has nothing to do with the zero value in total.