Reputation: 512
How could I access to those arguments? I have read that they are stored in r1, but I am not able to access them.
For example, in this code:
.global main
main:
ldr r2, [r1, #4]
ldr r0, [r2]
bx lr
If I execute the program with 7 value:
./program 7
echo $?
I got 55, that is the decimal ASCII representation of 7.
So I tried to add SUB line:
.global main
main:
ldr r2, [r1, #4]
sub r2,r2,#48 // to actually obtain 7
ldr r0, [r2]
bx lr
But I got 0. Why?
EDIT (it works):
.global main
main:
ldr r2, [r1,#4]
ldr r0, [r2]
sub r0, r0, #48
bx lr
But what I have not clear is, why doesn't it work if I use r0 instead of r2? Like this:
.global main
main:
ldr r0, [r1,#4]
sub r0, r0, #48
bx lr
Upvotes: 0
Views: 306
Reputation: 71516
#include <stdio.h>
int main ( int argc, char *argv[] )
{
printf("%d\n",argv);
return(0);
}
so.c: In function ‘main’:
so.c:5:12: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘char **’ [-Wformat=]
that is your first problem
#include <stdio.h>
int main ( int argc, char *argv[] )
{
printf("%d\n",argv[1][0]);
return(0);
}
./so 7
55
55 = 0x37
If you had gotten past that this would be your second problem
Could solve the first by simply asking the compiler to show you a path.
#include <stdio.h>
int main ( int argc, char *argv[] )
{
return(argv[1][0]);
}
0: e5913004 ldr r3, [r1, #4]
4: e5d30000 ldrb r0, [r3]
8: e12fff1e bx lr
Think about how the C function is called and then translate that to assembly. An array of pointers to strings.
And then depending on the instruction set you may have additional issues in the factorial function.
EDIT:
.global main
main:
ldr r2, [r1, #4] <--- address of the pointer to the string
sub r2,r2,#48 <---- hoses the pointer to the string
ldr r0, [r2] <---- who knows what this is reading
bx lr
Look at the code the compiler generated (assuming 7 is the first parameter on the command line ./so 7)
0: e5913004 ldr r3, [r1, #4] <---- pointer to string (param 1)
4: e5d30000 ldrb r0, [r3] <---- get first byte in string
r0 now contains 0x37
ldrb r0, [r3,#1] <----- If I added this line
r0 now contains 0x00 string termination
8: e12fff1e bx lr
Now think about Frant's answer, how you convert a string to a number if the string is some number in some base ("7", "0x123", "68", etc).
Upvotes: 2
Reputation: 5895
You are passing the string "7" as an argument, not the value 7, you have to convert it into a binary value.
Remember, the signature for the main function is int main(int argc, char** argv, char** envp)
.
That is, the number of argument will be in r0, the pointer to the array of the parameters strings will be in r1, and the pointer to the array of environment zero-terminated strings will be in r2.
In order to retrieve "7", you need to access argv1 - argv[0] will be the zero-terminated string containing path to the program you are executing.
If you are passing 1 to 9, you can just substract '0' or 0x30 in order to the value retrieved in argv1.
For other values than '1'.. '9', you should call atoi() from your assembly program, or convert it by yourself for the fun.
Procedure Call Standard for the ARM Architecture is a good read for understanding how to call C functions form assembly or vice versa.
Upvotes: 1