views:

94

answers:

3

I'm currently playing with ARM assembly on Linux as a learning exercise. I'm using 'bare' assembly, i.e. no libcrt or libgcc. Can anybody point me to information about what state the stack-pointer and other registers will at the start of the program before the first instruction is called? Obviously pc/r15 points at _start, and the rest appear to be initialised to 0, with two exceptions; sp/r13 points to an address far outside my program, and r1 points to a slightly higher address.

So to some solid questions:

  • What is the value in r1?
  • Is the value in sp a legitimate stack allocated by the kernel?
  • If not, what is the preferred method of allocating a stack; using brk or allocate a static .bss section?

Any pointers would be appreciated.

A: 

I've never used ARM Linux but I suggest you either look at the source for the libcrt and see what they do, or use gdb to step into an existing executable. You shouldn't need the source code just step through the assembly code.

Everything you need to find out should happen within the very first code executed by any binary executable.

Hope this helps.

Tony

Tony Lambert
A: 

Here's the uClibc crt. It seems to suggest that all registers are undefined except r0 (which contains a function pointer to be registered with atexit()) and sp which contains a valid stack address.

So, the value you see in r1 is probably not something you can rely on.

Some data are placed on the stack for you.

Artelius
Useful link, thanks.
Steve Smith
+1  A: 

Here's what I use to get a Linux/ARM program started with my compiler:

/** The initial entry point.
 */
asm(
"       .text\n"
"       .globl  _start\n"
"       .align  2\n"
"_start:\n"
"       sub     lr, lr, lr\n"           // Clear the link register.
"       ldr     r0, [sp]\n"             // Get argc...
"       add     r1, sp, #4\n"           // ... and argv ...
"       add     r2, r1, r0, LSL #2\n"   // ... and compute environ.
"       bl      _estart\n"              // Let's go!
"       b       .\n"                    // Never gets here.
"       .size   _start, .-_start\n"
);

As you can see, I just get the argc, argv, and environ stuff from the stack at [sp].

A little clarification: The stack pointer points to a valid area in the process' memory. r0, r1, r2, and r3 are the first three parameters to the function being called. I populate them with argc, argv, and environ, respectively.

Richard Pennington
Thanks. Is this setup documented anywhere that you know of?
Steve Smith
I'm sure it must be but I have to admit I figured it out using gdb.
Richard Pennington