1

I'm using the Raspberry Pi to learn ARM assembly. I'm still beginning but I would like to know how I can read the values of argv.

I figured out that the value of argc is held in register 0 (r0) at the beginning of a program, but I can't figure out where the argv value is stored. I assume it's somewhere in the stack, but I'm not able to find it.

Can someone help with this?


Edit: So the answer I marked as correct allowed me to find the values of argv. To summarize, the value of argc is found in register r0 when the program launches. r1 contains an address to an array of addresses. These addresses point to the relevant values of argv.

user668074
  • 1,111
  • 10
  • 16
  • 1
    They/it are on the stack. See [an example here](http://stackoverflow.com/questions/20369440/can-start-be-the-thumb-function/20379933#20379933). – artless noise Feb 28 '17 at 14:41
  • @artlessnoise They/it are on the stack in `_start`, by the time you reach `main` they should be in registers already. – Dmitry Grigoryev Feb 28 '17 at 14:45
  • @DmitryGrigoryev He doesn't have `main()` as he is coding in assembler! – artless noise Feb 28 '17 at 14:47
  • 1
    Also, I think that `argc` being in R0 is a happy co-incident. It should also be the first value on the stack. It is probably better to use that one as most 'C' library start up code uses this value. I don't have a canonical reference on that. – artless noise Feb 28 '17 at 14:52
  • 1
    @DmitryGrigoryev, What is the difference between the `_start` and `main` labels in assembly? I don't have a `_start` label. Maybe it's because I am using `gcc` as a linker? – user668074 Mar 01 '17 at 02:20
  • @user668074 I believe `gcc` should be run with `-nostdlib` parameter if you don't want it to include any bootstrap code in the executable. Then you should only have `_start` – Dmitry Grigoryev Mar 01 '17 at 08:36

1 Answers1

3

According to ARM ABI, the second primitive argument to a function should be stored in R1. Bear in mind that argv is a char**, i.e. an address pointing to a table of argc pointers. The first pointer in this table points to a NULL-terminated string containing the executable name, and following pointers point to individual arguments, also represented as NULL-terminated strings.

In case I'm mistaken, just build a simple program accessing argv and see where it takes it from:

int main (int argc, char *argv[])
{
  return argv[0][0];
}

Note that while you're using assembler, gcc will still include startup code from standard library in your program, defining the _start symbol for you and making C-style main function the entry point, so the above still applies to you. However, since you're learning assembler, you may be interested in getting rid of standard library completely, which is done with gcc -nostdlib. Note that you will need to provide your own code for _exit() function to be able to terminate your program properly. See this tutorial for a detailed walk-through.

Dmitry Grigoryev
  • 3,156
  • 1
  • 25
  • 53
  • Err, this is somewhat wrong. It is correct that a 'C' program will get things like this. However, an assembler program has no 'C' machinery so the question is how to get `argv` to R1. This answer assumes it is there already? – artless noise Feb 28 '17 at 14:46
  • 1
    @DmitryGrigoryev, I am not using inline assembler. I am using Assembly and compiling to object code with `as` and linking with `gcc`. I am debugging with `gdb`. In your answer you mention that `argv` is a pointer to a pointer, this might be where I am making my mistake. I will check that. – user668074 Mar 01 '17 at 02:13
  • @artlessnoise Turns out that linking with `gcc` includes that C machinery in the output by default. I have fixed my answer. – Dmitry Grigoryev Mar 01 '17 at 08:53