08
.pdfРаботает вызванная f1
1. Выполняется первая команда эпилога: movl %ebp, %esp
и %esp получает значение, которое он имел до выполнения команды
subl $8, %esp
выделившей память для локальных переменных, значения которых теперь становятся недоступными, а стек возвращается из состояния 5 к состоянию 4:
Состояние 4 |
Имя или |
Форма операнда |
|
значение |
элемента стека в |
|
элемента в |
режиме регистровой |
Вершина стека |
стеке |
адресации |
caller%ebp F |
0(%esp), 0(%ebp) |
|
|
RetAddr F |
4(%esp), 4(%ebp) |
|
|
|
|
P1 |
8(%esp), 8(%ebp) |
|
P2 |
12(%esp), 12(%ebp) |
|
... |
... |
|
PN |
4+4+4*(N-1)(%esp), |
|
|
4+4+4*(N-1)(%ebp) |
Старший адрес |
Восемь РОН F |
Не показаны |
1 |
Не показан. |
2. Выполняется вторая команда эпилога: popl %ebp
которая подготавливает к работе вызывающую функцию, восстанавливая (и удаляя из стека) значение %ebp, которое он имел до выполнения команды call.
Стек переходит из состояния 4 в состояние 2:
Состояние 2 |
Имя или |
Форма операнда |
|
значение |
элемента стека в |
|
элемента в |
режиме регист- |
Вершина стека |
стеке |
ровой адресации |
RetAddr F |
0(%esp) |
|
|
P1 |
4(%esp) |
|
P2 |
8(%esp) |
|
... |
... |
|
PN |
4+4*(N-1)(%esp) |
Старший адрес |
Восемь РОН F |
Не показаны |
1 |
Не показан. |
NBNB. Сейчас на вершине стека находится адрес возврата в вызывающую функцию. Именно это и нужно для выполнения команды ret. Она читает (и удаляет) из стека значение RetAddr и, помещая его в регистр %eip, передает управление вызывающей функции. При этом стек переходит в состояние 1:
Состояние 1 |
Имя или |
Форма операнда |
|
значение |
элемента стека |
|
элемента в |
в режиме |
|
стеке |
регистровой |
Вершина стека |
|
адресации |
P1 |
0(%esp) |
|
|
P2 |
4(%esp) |
|
... |
... |
|
PN |
4*(N-1)(%esp) |
Старший адрес |
Восемь РОН F |
Не показаны. |
1 |
Не показан. |
NBNB. В стеке сейчас только параметры и РОН.
Работает вызывающая функция
Выполняется команда очистки стека от параметров: addl $L,%esp
(L — константа, равная суммарной длине в байтах всех параметров — для 2 параметров это 8). Стек переходит в состояние 0:
Состояние 0 |
Имя или |
Форма операнда |
|
значение |
элемента стека в |
|
элемента в |
режиме регист- |
Вершина стека |
стеке |
ровой адресации |
%edi |
0(%esp) |
|
|
%esi |
4(%esp) |
|
|
|
|
%ebp |
8(%esp) |
|
|
|
|
%esp |
12(%esp) |
|
|
|
|
%ebx |
16(%esp) |
|
|
|
|
%edx |
20(%esp) |
|
|
|
|
%ecx |
24(%esp) |
|
|
|
|
%eax |
28(%esp) |
Старший адрес |
|
|
1 |
32(%esp) |
Выполняется команда восстановления РОН: popa и стек переходит в исходное состояние:
Исходное |
Имя или |
Форма операнда |
состояние |
значение |
элемента стека в |
|
элемента в |
режиме регист- |
Вершина стека |
стеке |
ровой адресации |
1 |
0(%esp) |
Выводы
1.По соглашениям о связях ABI команды передачи параметров в стек, команда call, команды пролога и, по желанию программиста, команды резервирования памяти для локальных переменных, создают в стеке для каждой вызываемой функции отдельную, принадлежащую ей структуру данных — кадр стека.
2.Операнды команд для адресного доступа к параметрам функции и локальным переменным в кадре стека задаются в виде смещение(%ebp), где смещение выбирается из таблицы состояния стека 5. В частности, смещения параметров положительные — первого 8 — форма операнда 8(ebp), второго 12 — форма операнда 12(ebp) и т. д. Смещения локальных переменных в стеке отрицательные — первой -4 — форма операнда -4(ebp), следующей -8 — форма операнда -8(ebp) и т. д.
3.После формирования кадра стека регистр %esp больше не нужен для работы вызванной функции, что обеспечивает возможность вложенных вызовов других функций с формированием их собственных кадров стека.
4.В каждый момент времени существует столько кадров стека, сколько функций не выполнили код эпилога и команду ret.
5.Код эпилога обеспечивает выход из функции и деактивацию ее кадра стека, которая завершается в вызывающей функции командами очистки стека от параметров.