Что такое регистры ESP и EBP?

Я обнаружил, что регистр ESP - это текущий указатель стека, а EBP - базовый указатель для текущего кадра стека. Однако я не понимаю этих определений (я только начинаю изучать, как писать код на ассемблере).

Я понимаю, что ESP указывает на сам стек, а EBP указывает на то, что находится на вершине стека. Но это только мои догадки, и они, скорее всего, неверны. В противном случае, что бы означало следующее утверждение?

MOV EBP, ESP    

РЕДАКТИРОВАТЬ: Я думаю, что утверждение выше является опечаткой моей книги. Я думаю, что это должен быть EBX вместо EBP

5 ответов

Решение

esp - указатель стека, ebp - это / был для фрейма стека, чтобы при вводе функции ebp мог получить копию esp в этот момент, все в стеке до этого, адрес возврата, параметры и т. д. и т. д. глобальные для этой функции (локальные переменные) теперь будут находиться на статическом расстоянии от указателя фрейма стека в течение всей функции. esp теперь может свободно бродить по желанию компилятора и может использоваться при вложении в другие функции (каждая из них должна сохранять ebp естественным образом).

это ленивый способ управления стеком. значительно упрощает отладку компилятора, облегчает понимание кода, сгенерированного компилятором, но записывает регистр, который в противном случае мог бы быть универсальным.

Обычно EBP используется для резервного копирования ESP, поэтому, если ESP изменяется кодом функции, все, что требуется для восстановления ESP - это mov ESP, EBP. Также, поскольку EBP обычно остается неизменным кодом в функции, его можно использовать для доступа к переданным параметрам или локальным переменным без необходимости корректировать смещения.

Для использования "стекового фрейма" EBP помещается в стек в начале любой функции, поэтому значение EBP, помещаемое в стек, является значением EBP из функции, вызвавшей текущую функцию. Это позволяет коду или отладчику "отследить" все случаи, когда EBP помещался в стек, и каждый экземпляр значения EBP в стеке можно рассматривать как базовый указатель кадра стека.,

Обратите внимание, что некоторые компиляторы имеют опцию "опустить указатели фреймов", в этом случае EBP не используется для сохранения ESP или в качестве указателя фрейма стека. Вместо этого компилятор отслеживает ESP, и все локальные смещения являются смещениями от текущего значения ESP.

EBP и ESP - это пережитки эпохи, когда, например, у компиляторов не было статического анализа, чтобы определить, сколько байтов стека требуется при вызове функции. Кроме того, стек должен был динамически увеличиваться и уменьшаться во время выполнения функции, прерывания позволили бы очистить весь стек от 0 до SP, а код спагетти был стандартом де-факто. Фактически прерывания (и передача параметров только через регистры) были разработанным методом для вызова функций ядра.

В этих условиях необходимо иметь фиксированную точку стека, в которой всегда найден адрес возврата вызывающей стороне, локальные переменные и аргументы функции. Таким образом bp Регистрация была оправдана. В этой архитектуре bp было разрешено индексировать ([bp - 300h]), но sp не было. Те коды операций / инструкции, которые можно было бы интерпретировать как mov ax, [sp + 1111h] были повторно использованы для других целей.

В 386+ и благодаря введению "E" ESP приобрел свойство смещения. В это время EBP был освобожден от единственной цели, как esp был в состоянии справиться с обеими задачами.

Обратите внимание, что даже сейчас EBP указывает на память через сегмент стека, так же, как ESP, EBX и BX используют DS.

Регистр ESP является указателем стека для системного стека. Он редко изменяется непосредственно программой, но изменяется, когда данные помещаются в стек или извлекаются из стека. Одно из применений стека - вызовы процедур. адрес инструкций, следующих за инструкцией вызова процедуры, сохраняется в стеке. указатели регистров EBP на базу. обычно единственный элемент данных, к которому осуществляется доступ в стеке, - это тот, который находится наверху стека. Хотя регистр EBP часто используется для обозначения фиксированной точки в стеке, отличной от вершины стека, например, такими данными являются параметры. Они смещены от вершины EBP стека базового указателя после адреса возврата. Итак, вы увидите что-то вроде EBP+0x8, EBP+0xC, это параметры как в 1 и 2 соответственно.

Понимание стека очень важно при программировании на языке ассемблера, поскольку это может повлиять на соглашения о вызовах, которые вы будете использовать, независимо от типа. Например, даже cdecl или __stdcall также зависят от регистров ESP и EBP, а другие в некоторой степени зависят от некоторых регистров и стека.

Esp указывает на верхнюю часть кадра стека текущей запущенной функции. Ebp указывает на старый Ebp (старый означает перед функцией, которая выполняется в данный момент). Итак, если у вас есть функция Somefunction(); это будет вызвано в основной функции через мгновение (это пример, не кричите на меня), а затем, когда мы входим в него, создается стек, вы знаете всю черную магию, тогда Ebp, который находится внутри Somefunction(); укажет на Ebp предыдущей функции, которая является основной функцией, поскольку Somefunction(); звонили оттуда.

Другие вопросы по тегам