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
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
eret
?
Então orsp
é 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
é o registro usado para a função pai para utilizar o retorno de sua função filho. Éeax
explicitamente usado para isso ou isso é apenas uma convenção com meu compilador e arquitetura?