Недавно я изучал сборку x86 для обратного проектирования, и в моем руководстве есть предложение, в котором говорится, что Ebp указывает на старый Ebp, однако я этого не понимаю, это сбивает с толку.
Я посмотрел на другие сообщения об этом, но никто не ответил на мой вопрос.
... сделает работу с esp
утомительной. Кроме того, аргументы остаются с фиксированным смещением независимо от того, сколько места для локальных переменных выделено и сколько регистров сохранено.
Смысл одного указателя кадра, ссылающегося на другой, заключается в том, что это создает связанный список кадров стека, каждый кадр стека может использоваться для идентификации предыдущего (вызывающего, вызывающего) кадра стека — это означает, что (A) отладчик может отследить вызов стек, (B) мы можем раскрутить стек для обработки исключений (catch/throw).
(Обратите внимание, что для полноты этих заданий требуются некоторые дополнительные действия/информация, а также то, что механизм указателя кадра является лишь одним из нескольких способов выполнения трассировки стека.)
Текущее ebp
относится к месту, где текущий кадр сохранил предыдущее значение ebp
.
Это создает классический односвязный список. Итак, разыменуйте текущий ebp
и получите значение априора ebp
, сделайте это с априором и получите априор ebp
.
Поскольку предыдущее ebp
помещается как первое нажатие вновь вызываемой функции, которая была вызвана с помощью некоторой инструкции вызова, мы знаем, что в стеке есть адрес возврата непосредственно над каждым старым значением ebp
.
Поскольку адрес возврата всегда находится рядом с ebp
, и мы можем проследить каждый ebp
до его вызывающей стороны (фрейм вызывающей стороны), мы можем найти код, который выполнил вызов — для этого требуется использовать обратный адрес и некоторую проверку диапазонов для определения вызывающая функция. Таким образом, ключевым элементом связанного списка, созданного значениями ebp
, указывающими на предыдущий кадр, является доступ к адресам возврата в кадрах стека, которые можно использовать для идентификации функции (и даже места в функции), вызвавшей вызов.
поэтому я читал комментарии и ответы и понимаю, что Ebp указывает на Ebp из предыдущего кадра стека. Я правильно понимаю?
Да, классический односвязный список. @fre ebp
указывает на место в текущем кадре, где хранится предыдущий ebp
, поэтому разыменуйте ebp
и получите значение Prior ebp
, сделайте это с Prior и получите априор ebp
. Непосредственно над каждым сохраненным/предыдущим ebp
находится адрес возврата, поэтому вы можете найти код, который выполнил вызов — обычно это требует некоторой проверки диапазонов для идентификации вызывающей функции.
я не знаю, как я могу принять комментарий как ваш ответ, вы можете написать его как ответ, и я отмечу его?
@fre, хорошо, надеюсь, что редактирование поможет.
Когда используются указатели кадров, у функции есть пролог (если только он не голый), который выглядит как
push ebp / mov ebp, esp
. Вы можете видеть, чтоebp
перезаписывается значениемesp
, но до этого оно помещается в стек. Таким образом, старое значениеebp
находится в стеке, но поскольку указатель стека был скопирован вebp
, это новое значениеebp
указывает на старое. Один раз нарисовать это на бумаге очень поможет. Указатель фрейма полезен, потому что аргументы находятся в стеке (не все из них зависят от соглашения о вызовах) и доступ к аргументу при отправке аргументов вызова...