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

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

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

MOV EBP, ESP    

Сноска 1: Примечание редактора: Да, это неверно. В стандартной терминологии «вершина стека» - это точка, на которую указывает ESP, даже если это самый низкий адрес в кадре стека. По аналогии со структурой данных стека, которая растет вверх, хотя стек вызовов на x86 (как и большинство ISA) растет вниз.


person Lucas Alanis    schedule 12.02.2014    source источник
comment
EBX и EBP - разные регистры.   -  person Babken Vardanyan    schedule 12.02.2014


Ответы (4)


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

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

person old_timer    schedule 12.02.2014
comment
Спасибо. Для всех, кто все еще пытается понять, для меня ключевым моментом было сказать это самому себе: отправить ebp в стек для резервного копирования ebp. Затем переместите esp на ebp. Теперь мы можем играть с esp. Перед возвратом функции переместите обратно ebp в esp, чтобы восстановить то, что было до того, как мы переместили esp в ebp. Затем нажмите ebp, чтобы восстановить EBP из вершины стека. - person trogne; 26.09.2019
comment
Все дело в восстановлении стека и регистров до того, что было до вызова функции. - person trogne; 26.09.2019
comment
Итак, это эквивалент MIP $ ra? - person mark_infinite; 11.01.2021

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

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

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

person rcgldr    schedule 12.02.2014

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

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

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

Обратите внимание, что даже сейчас EBP указывает на память через сегмент (SS) стека, как и ESP. Другие режимы адресации (без ESP / EBP в качестве основы) по умолчанию относятся к сегменту DS. (абсолютный, DI, SI и / или BX в 16-битном режиме, а в 32-битных режимах адресации любой регистр может быть базовым в режиме адресации).

person Aki Suihkonen    schedule 12.02.2014
comment
Я считаю ваш ответ достаточно информативным, но я не уверен, что вы имеете в виду под самым последним предложением: EBX и BX используют DS.? - person Огњен Шобајић; 16.05.2014
comment
Исторически у IA были сегментные регистры; CS для кода, DS / ES для данных и SS для стека. Каждый сегмент одновременно обращался только к 64 КБ памяти. 386 имел ту же архитектуру, добавляя FS и GS, но теперь каждый сегмент можно было настроить для доступа от 1 байта до 4 ГБ памяти. Каждая инструкция или режим адресации имеет неявный сегментный регистр, через который осуществляется доступ к памяти. Даже более поздняя модель плоской памяти стала стандартом де-факто, где каждый сегментный регистр видит все (кроме ядра, которое резервирует, например, регистр GS). - person Aki Suihkonen; 17.05.2014

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

введите описание изображения здесь

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

person Peter    schedule 20.03.2020
comment
Обратите внимание, что все это применимо только к коду, который использует EBP в качестве указателя кадра. В современных системах это необязательно. Сборки отладки все еще делают это. Сами соглашения о вызовах, такие как stdcall, ничего не определяют о том, как вызывающий или вызываемый абонент должен использовать EBP. Совершенно нормально загрузить аргумент стека с чем-то вроде mov eax, [esp + 4] / ret 4 для реализации функции stdcall, которая возвращает целочисленный аргумент. - person Peter Cordes; 21.03.2020