Reputation: 19
I'm new to ARM assembly and am trying to translate some easy code snippets from C to assembly. I'm not sure if I am using ldr and str correctly (although I feel like ive tried everything) and I keep getting seg fault when I try to run it.
The C code is
int main() {
int x = 10;
int y = 5;
int z = 20;
int min = y;
if (x < min) {min = x;}
if (z < min) {min = z;}
return min;
}
My assembly code:
.global main
.text
main:
push {ip, lr}
mov r0, #10
mov r1, #5
mov r2, #20
str r3, [r1]
cmp r0, r3
bge done
str r0, [r3]
cmp r2, r3
bge done
str r2, [r3]
done:
ldr r0, [r3]
pop {ip, pc}
Upvotes: 1
Views: 276
Reputation: 22420
The C code is
int main() {
int x = 10;
int y = 5;
int z = 20;
int min = y;
if (x < min) {min = x;}
if (z < min) {min = z;}
return min;
}
Don't use ldr
and str
as these store a registers value to memory. For example str rX, [rY]
means to use the value of 'rY' as a memory address to store the value of 'rX'. There is no need to use memory when you have many available registers. For example,
mov r0, #5 ; min = y = #5
mov r1, #10 ; x = 10
mov r2, #20 ; z = 20
cmp r1, r0 ; if (x < min)
movlt r0, r1 ; min = x
cmp r2, r0 ; if (z < min)
movlt r0, r2 ; min = z
mov pc, lr ; return min (is r0)
is close if not complete. Please review my register use as some maybe transposed. As well you might consider if you need signed or unsigned. Your original used bge done
which will not work if 'x > y > z'. You need to use 'less than' as per the 'C' code.
I would suggest not using a compiler to start with for very simple code like this. If you have many variables, then start with a compiler. After you attempt something, see what the compiler does. You may have a better structural idea than the compiler in some cases; probably not for a numerical problem like this. If you go to the compiler right away it will be more difficult to think of alternate attacks on coding the function. Often ideas from both your original attempt and the compiler will combine for something quite nice.
Upvotes: 1
Reputation: 2599
TonyK's answer covers the source of your mistakes pretty well. It strikes me that it might benefit you to see how a compiler would deal with the compilation of a simple program like this; seeing the compiler allocate space on the stack for these variables, and seeing how it uses LDR
and STR
correctly, could well help you to learn.
If you're using gcc, try adding -S -O1
to the compiler options to enable mild optimisation (-O1
) and to request assembly language as the output (-S
). The output will interleave the original C code into the generated assembly language, which will hopefully make it easier to understand.
Upvotes: 0
Reputation: 17114
OK, for each of your variables, you have to decide where you are going to store it:
Your function is mixing these up disastrously. You store x,y,z
, in registers r0,r1,r2
, but then you treat y
as if it was stored at the address 5
, whereas it is in fact stored in the register r1
. You don't want to use the memory access instruction str r3, [r1]
here, because nothing is in memory; just mov r3,r1
is enough.
The rest of the code is similarly dysfunctional, but I won't go into details. Your function is simple enough that you have more than enough registers to go round, so I suggest you re-write it to use registers for all variables. No ldr/str
instructions at all, just mov
instructions.
And look at the assembly code generated by your C compiler to get a feel for more complicated situations where some or all variables have to be stored on the stack.
Good luck!
Upvotes: 1