Wie wird der Stapelzeiger in diesem Programm mit call and ret geändert?
Meine Fragen beziehen sich auf die Aktionen, die scheinbar zwischen den Zeilen stattfinden, wenn sich der Kontext ändert, insbesondere in Bezug aufRSP
undRBP
.
Angesichts dieses sehr einfachen Programms:
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 }
Alle Funktionen beginnen mit Pushrbp
was ich verstehe, ist es, den übergeordneten Kontext auf dem Stapel zu erhalten. Woher weiß die übergeordnete Funktion, wie sie sich selbst neu aufbaut? Sind die notwendigen Schritte eingebautcall
undret
?
Dann ist diersp
wird immer verschoben nachrbp
. Wie ich gelesen habe, setzt dies die neue Stapelbasis in den Kontext der aktuellen Funktion. Was ich anscheinend nicht herausfinden kann, ist, wann oder wie der Stapelzeiger an erster Stelle auf diesen Punkt gesetzt wurde. Ich vermute, dass der Aufruf der Assembly-Funktion dies tut, ist das, was passiert?
Wenn eine Methode zurückgegeben wird, sieht es schließlich so auseax
ist das Register, das für die übergeordnete Funktion verwendet wird, um die Rückgabe ihrer untergeordneten Funktion zu verwenden. Isteax
Wird dies explizit verwendet oder handelt es sich nur um eine Konvention mit meinem Compiler und meiner Architektur?