Что именно заставляет вас верить, что вещи хранятся ниже указателя stack . Все, что я вижу, это отрицательное смещение от ebp
, которое является указателем frame .
Это обычно используется как указатель на следующий кадр стека по сравнению с текущим по ряду причин.
- По обе стороны от
ebp
находятся параметры, передаваемые этой функции (выше ebp
), и локальные данные для этой функции (ниже ebp
). Использование -0x10(%ebp)
просто означает, что вы что-то делаете с локальной переменной.
- Легко вернуться к предыдущему кадру стека, просто загрузив
%esp
с %ebp
и вернувшись.
Конечно, вы можете достичь чего-то ниже %esp
, но это будет зависеть от загружаемых данных, которые на самом деле не показаны в вашем примере.
«Диаграмма» может помочь:
+------------------------+
| Parameters passed to x |
+------------------------+
| Return address |
%ebp +------------------------+
| Locals for x |
%esp +------------------------+
Моя память об этом ржавая (конкретные инструкции могут быть не точными, но они должны быть достаточно хорошими, чтобы указать концепцию, лежащую в основе), но типичная последовательность вызова функций:
- вызывающая сторона помещает параметры в стек (
push
, push
, ...).
- вызывающий абонент помещает текущий
%ebp
в стек (push %ebp
).
- вызывающий груз
%ebp
с %esp%
(mov %ebp, %esp
).
- звонящий звонит вызываемому абоненту (
call XYZ
).
- вызываемый абонент выделяет место для местных жителей (
sub %esp,N
).
- вызываемый может затем использовать
(%ebp+N)
для параметров, (%ebp-N)
для местных жителей.
А для возврата:
- загружаемых вызовов
%esp
с %ebp
(mov %esp, %ebp
).
- вызываемый абонент возвращается к вызывающему абоненту (
ret
).
- вызывающий абонент выскакивает предыдущий
%ebp
из стека (pop %ebp
).
- вызывающий абонент очищает секцию параметров (
add %esp,N
).