¿Cómo se cambia el puntero de la pila en este programa con call y ret?

Mis preguntas se refieren a las acciones que parecen suceder entre líneas cuando se cambia el contexto, especialmente en relación conRSP yRBP.

Dado este programa muy simple:

Reading symbols from ./function_call...done.
(gdb) disass main
Dump of assembler code for function main:
   0x00000000004004d6 <+0>: push   rbp
   0x00000000004004d7 <+1>: mov    rbp,rsp
   0x00000000004004da <+4>: mov    esi,0x2
   0x00000000004004df <+9>: mov    edi,0x1
   0x00000000004004e4 <+14>:    call   0x4004b6 <add_and_7>
   0x00000000004004e9 <+19>:    mov    eax,0x0
   0x00000000004004ee <+24>:    pop    rbp
   0x00000000004004ef <+25>:    ret    
End of assembler dump.
(gdb) disass add_and_7
Dump of assembler code for function add_and_7:
   0x00000000004004b6 <+0>: push   rbp
   0x00000000004004b7 <+1>: mov    rbp,rsp
   0x00000000004004ba <+4>: mov    DWORD PTR [rbp-0x14],edi
   0x00000000004004bd <+7>: mov    DWORD PTR [rbp-0x18],esi
   0x00000000004004c0 <+10>:    mov    DWORD PTR [rbp-0x4],0x7
   0x00000000004004c7 <+17>:    mov    edx,DWORD PTR [rbp-0x14]
   0x00000000004004ca <+20>:    mov    eax,DWORD PTR [rbp-0x18]
   0x00000000004004cd <+23>:    add    edx,eax
   0x00000000004004cf <+25>:    mov    eax,DWORD PTR [rbp-0x4]
   0x00000000004004d2 <+28>:    add    eax,edx
   0x00000000004004d4 <+30>:    pop    rbp
   0x00000000004004d5 <+31>:    ret    
End of assembler dump.
(gdb) list
1   int add_and_7( int num1, int num2 ) {
2       int seven = 7;
3       return num1 + num2 + seven;
4   }
5   
6   int main() {
7       add_and_7( 1, 2 );
8       return 0;
9   }

Todas las funciones comienzan con pushrbp que, según tengo entendido, está preservando el contexto principal en la pila. ¿Cómo sabe la función principal cómo reconstruirse? ¿Están los pasos necesarios integrados encall yret?

Entonces larsp siempre se mueve arbp. Como he leído, esto establece que la nueva base de la pila esté en el contexto de la función actual. Lo que parece que no puedo entender es cuándo o cómo se configuró el puntero de la pila en ese punto en primer lugar. Mi mejor conjetura es que la llamada a la función de ensamblaje hace esto, ¿qué está pasando?

Por último, cuando un método regresa, parece queeax es el registro que se utiliza para que la función principal utilice el retorno de su función secundaria. Eseax ¿Se usa explícitamente para esto o es solo una convención con mi compilador y mi arquitectura?

Respuestas a la pregunta(2)

Su respuesta a la pregunta