¿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?