2

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)?

George_H
  • 93
  • 2
  • 14
  • "When I print this out" - what exactly are you printing? `total`? `r4`? – ForceBru Feb 09 '20 at 16:38
  • 1
    first off are r0, r1 and r2 pointers to the variable (int *x, int *y ...) or do they contain the value themselves? [r0] is indirect r0 is not add r2,r0,r1 will add the two together and put the result in the third if they are not the address to the value but are the value – old_timer Feb 09 '20 at 16:38
  • @ForceBru, I'm trying to print out the total variable. – George_H Feb 09 '20 at 16:39
  • 1
    read the arm documentation please ldr r4,[r0] means use the value in r0 as an address read the 32 bit value in memory at that address and put it in r4. then ldr r4,[r1] does the same thing but uses the contents of r1 as the address and r4 is now overwritten with the new value losing whatever you did in the ldr r4,[r0]. if r0 and r1 are addresses then add r2,r0,r1 is just adding addresses/pointers not values. and str r4,[r2] now puts r4 which you read from the address of r1 into the address of r0,r1, there have been no data values used at this point – old_timer Feb 09 '20 at 16:40
  • @old_timer, Yes. x = 1, y = 2, total = 0. So I'm trying to get it so printing out total should produce 3. – George_H Feb 09 '20 at 16:41
  • 1
    nothing about your code will do that your code is doing *(&x + &y) = *y; – old_timer Feb 09 '20 at 16:43
  • you are lucky you are not crashing – old_timer Feb 09 '20 at 16:44
  • where did you put 1 and 2, I dont see that in your code, provide a complete example – old_timer Feb 09 '20 at 16:44
  • The integers are in my .c file, and the assembly in my .s file. – George_H Feb 09 '20 at 16:46
  • please show the C file that is calling this asm code, please provide a complete example, there is more than one way to do this so we cant help without seeing what you are trying to do – old_timer Feb 09 '20 at 16:46
  • I've edited my original post with the .c file. Apologies. – George_H Feb 09 '20 at 16:49

1 Answers1

3

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.

old_timer
  • 69,149
  • 8
  • 89
  • 168
  • Ahh, that make's sense now. I thought I might of been overwiting the registers with others. It also makes sense with the registers too. Thank you for your help! – George_H Feb 09 '20 at 17:03
  • the arm docs do a pretty good job with pseudo code for each instruction, I would probably learn from the armv5 architectural reference manual vs the armv7-ar because the latter has a lot more protection and execution mode overhead that is part of that pseudocode. either work though and would show that ldr r4,[r0] means read the value at the address contained in r0 into the register r4. – old_timer Feb 09 '20 at 17:06
  • 1
    dont just turn that in as your homework answer. I recommend at least change it without using r3 or higher (not r4, not r5, etc) only use r0,r1,r2, it will then not look compiler generated – old_timer Feb 09 '20 at 17:14