Мои вопросы относятся к действиям, которые происходят между строками при изменении контекста, особенно в отношении RSP
и RBP
.
Учитывая эту очень простую программу:
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 }
Все функции начинаются с push rbp
, который, насколько я понимаю, сохраняет родительский контекст в стеке. Откуда родительская функция знает, как перестроить себя? Встроены ли необходимые шаги в call
и ret
?
Затем rsp
всегда перемещается на rbp
. Как я читал, это устанавливает новую базу стека в контексте текущей функции. Что я не могу понять, так это когда и как указатель стека был установлен в эту точку в первую очередь. Насколько я понимаю, это делает вызов функции ассемблера, это то, что происходит?
Наконец, когда метод возвращает значение, кажется, что eax
— это регистр, который используется родительской функцией для использования возврата ее дочерней функции. Используется ли eax
для этого явно или это просто соглашение с моим компилятором и архитектурой?