Como o ponteiro da pilha é alterado neste programa com call e ret

Minhas perguntas dizem respeito às ações que parecem acontecer entre as linhas quando o contexto é alterado, especialmente em relação aRSP eRBP.

Dado este programa muito simples:

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 as funções começam com pushrbp&nbsp;que, como eu entendo, está preservando o contexto pai na pilha. Como a função pai sabe como se reconstruir? As etapas necessárias estão incorporadascall&nbsp;eret?

Então orsp&nbsp;é sempre movido pararbp. Como eu li, isso define a nova base da pilha para estar no contexto da função atual. O que eu não consigo entender é quando ou como o ponteiro da pilha foi definido para esse ponto em primeiro lugar. Meu melhor palpite é que a chamada de função de montagem faz isso, é isso que está acontecendo?

Por fim, quando um método retorna, parece queeax&nbsp;é o registro usado para a função pai para utilizar o retorno de sua função filho. Éeax&nbsp;explicitamente usado para isso ou isso é apenas uma convenção com meu compilador e arquitetura?