Nick
Nick

Reputation: 326

Understanding asm instructions in basic C program in GDB

In my attempt to understand memory layout in a process and learn assembly I've written a basic C program on Pi3 (ARM) and disassembled it with GDB but as I'm new to this I need help understanding it.

Essentially I'm trying to understand and spot in assembly where variables are stored (BSS, DATA, TEXT memory segments) and also understand and follow the stack frames.

I've only displayed the main function - there were other segments on the debug screen so let me know if they would help too!

I understand what the individual instructions are doing for the most part, but what I'd like to know is:

  1. The first 3 lines are concerned with the stack pointer is this setting up the stack frame for the main function?

  2. At x0x10414 it's using the value for age, is this where the local variable is popped onto the stack as part of the frame for the main function?

  3. At x0x1041c is that the return value as I assumed that was pushed onto the stack too as part of the frame?

  4. Where is the stack flushed at the end of the function?

int main () {
        int age = 30;
        int salary;
        return 0;
}
0x10408 <main>                  push   {r11}           ; (str r11, [sp, #-4]!)
x0x1040c <main+4>               add    r11, sp, #0                           
x0x10410 <main+8>               sub    sp, sp, #12                           
x0x10414 <main+12>              mov    r3, #30                               
x0x10418 <main+16>              str    r3, [r11, #-8]                        
x0x1041c <main+20>              mov    r3, #0                                
x0x10420 <main+24>              mov    r0, r3                                
x0x10424 <main+28>              add    sp, r11, #0                           
x0x10428 <main+32>              pop    {r11}           ; (ldr r11, [sp], #4) 
x0x1042c <main+36>              bx     lr   

Upvotes: 3

Views: 132

Answers (1)

E. van Putten
E. van Putten

Reputation: 673

  1. Yes, you are right. Register r11 is used as frame pointer. This frame pointer serves as a reference to where your local variables are stored on the stack. Note that the original frame pointer from the caller must be preserved (so it is saved and restored later).
  2. Almost. It happens one line later, it stores it on the stack at [r11 - 8]. Remember that r11 is the frame pointer, everything is relative w/respect to that.
  3. It is not pushed on the stack. It is simply returned in register r0. It's common on a lot of platforms that a general purpose register is used. Then the stack need not to be used for simple and plain return values (like your integer). I guess this is for performance reasons as registers are faster than memory accesses.
  4. I don't know what you mean with flushed. What happens here is that the function sets things up the way it likes, and afterwards reverts those changes. The content of the stack might still contain values that the function used. It's just that the pointers are reset to their original locations. First at the beginning of the function the original frame pointer (r11) is saved/pushed on the stack. Then the value of the stack pointer becomes the new frame pointer. At the end of the function the stack pointer is returned to where it was (by overwriting it with r11) and finally r11 itself is restored too by popping it off the stack.

Upvotes: 3

Related Questions