c — Выравнивание значения в ESP на 16 байт
Вопрос задан
Изменён 6 лет 9 месяцев назад
Просмотрен 1k раза
Дизассемблировал такую простую программу:
push ebp mov ebp, esp and esp, 0FFFFFFF0h sub esp, 10h mov eax, offset aHelloWorld ; "hello, world\n"
Строка and esp, 0FFFFFFF0h
мне всегда мозолила глаза, а ее смысл в книгах по реверсу не объясняется. Пишут, что это выравнивание значения в ESP
по 16-байтной границе, но «выравнивание», «обнуление первых четырех бит» и «16 байт» у меня никак не складываются в завершенную идею. Что здесь происходит? Для чего это? Почему для выравнивания на 16 байт надо обнулить 4 бита?
Выравнивание я понимаю как заполнение кусков памяти до кратности какому-то числу.
x
рассчитываются следующим образом:x & ~(n - 1) // вниз, до ближайшего меньшего числа кратного n (x + n - 1) & ~(n - 1) // вверх, до ближайшего большего числа кратного n
Неиспользуемые куски памяти называются padding и строго говоря к выравниванию отношения не имеет. При этом они могут быть ничем не заполнены (dup alignment (?)
).
Поскольку стек растет вниз, то его выравниваниют снизу, т.е. при помощи
and esp, ~0xf
Стек «растет» в сторону уменьшения адресов:
То есть получив ESP
и желая его выровнять, отсекаются младшие 4 бита (при этом ESP
станет указывать на участок памяти, находящийся через некоторое количество байт от «прошлого» ESP
). Тогда да, в стеке могут образовываться «дырки». Так сказано в документации, что ESP
выравнен по границе 16 бит. Насчёт целесообразности — вопрос к разработчикам, но они утверждают, что это увеличивает производительность.
3
Зарегистрируйтесь или войдите
Регистрация через Google
Регистрация через Facebook
Регистрация через почту
Отправить без регистрации
Почта
Необходима, но никому не показывается
Отправить без регистрации
Необходима, но никому не показывается
Нажимая на кнопку «Отправить ответ», вы соглашаетесь с нашими пользовательским соглашением, политикой конфиденциальности и политикой о куки
Рекомендации по написанию кода Prolog-Epilog
Twitter LinkedIn Facebook Адрес электронной почты
- Статья
- Чтение занимает 2 мин
Блок, относящийся только к системам Microsoft
Прежде чем писать собственные последовательности кода пролога и эпилога, важно понимать, как размещается кадр стека. Также полезно знать, как использовать __LOCAL_SIZE
символ.
Макет кадра стека
В данном примере показан стандартный код пролога, который может присутствовать в 32-разрядной функции.
push ebp ; Save ebp mov ebp, esp ; Set stack frame pointer sub esp, localbytes ; Allocate space for locals push <registers> ; Save registers
Переменная localbytes
представляет число байтов, которые требуются в стеке для локальных переменных, а переменная <registers>
— это заполнитель, представляющий список сохраняемых в стеке регистров. После проталкивания регистров можно разместить в стеке все другие необходимые данные. Ниже приведен соответствующий код эпилога.
pop <registers> ; Restore registers mov esp, ebp ; Restore stack pointer pop ebp ; Restore ebp ret ; Return from function
Стек всегда расширяется в направлении вниз (от старших адресов памяти к младшим). Указатель базы (ebp
ebp
. Область локальных переменных начинается с адреса ebp-4
. Для доступа к локальным переменным необходимо вычислить смещение от ebp
путем вычитания соответствующего значения из ebp
.__LOCAL_SIZE
Компилятор предоставляет символ для __LOCAL_SIZE
использования в блоке встроенного ассемблера кода пролога функции. Этот символ служит для выделения пространства локальным переменным в кадре стека пользовательского кода пролога.
Компилятор определяет значение __LOCAL_SIZE
. Это значение представляет общее количество байтов всех определяемых пользователем локальных переменных и временных переменных, создаваемых компилятором. __LOCAL_SIZE
может использоваться только в качестве немедленного операнда; Его нельзя использовать в выражении. Значение этого символа не следует изменять и переопределять. Пример:
mov eax, __LOCAL_SIZE ;Immediate operand--Okay mov eax, [ebp - __LOCAL_SIZE] ;Error
В следующем примере голой функции, содержащей пользовательские последовательности пролога и эпилога, используется __LOCAL_SIZE
символ в последовательности пролога:
// the__local_size_symbol. cpp // processor: x86 __declspec ( naked ) int main() { int i; int j; __asm { /* prolog */ push ebp mov ebp, esp sub esp, __LOCAL_SIZE } /* Function body */ __asm { /* epilog */ mov esp, ebp pop ebp ret } }
Завершение блока, относящегося только к системам Майкрософт
См. также
Вызовы функции Naked
Сборка— что такое регистры ESP и EBP?
спросил
Изменено 1 месяц назад
Просмотрено 126 тысяч раз
Я обнаружил, что регистр ESP является текущим указателем стека, а EBP — базовым указателем для текущего фрейма стека. Однако я не понимаю этих определений (я только начинаю учиться программировать на ассемблере).
Насколько я понимаю, ESP указывает на сам стек, а EBP указывает на то, что находится на вершине стека 1 . Но это только мои догадки и они скорее всего неверны. В противном случае, что бы означало утверждение, подобное следующему?
МОВ ЭБП, ЭСП
Сноска 1: Примечание редактора: Да, это неверно. В стандартной терминологии «вершина стека» — это точка, на которую указывает ESP, даже если это самый нижний адрес в кадре стека. По аналогии со структурой данных стека, которая растет вверх, хотя стек вызовов на x86 (как и в большинстве ISA) растет вниз.
- сборка
- x86
- стек вызовов
- стек-фрейм
1
esp — это указатель стека, ebp — это/было для фрейма стека, чтобы при входе в функцию ebp мог получить копию esp в этой точке, все в стеке до этого, адрес возврата, переданные параметры и т. д. и вещи, которые являются глобальными для этой функции (локальные переменные), теперь будут находиться на статическом расстоянии от указателя кадра стека на время действия функции. esp теперь может свободно перемещаться по желанию компилятора и может использоваться при вложении в другие функции (каждая должна сохранять ebp естественно).
это ленивый способ управления стеком. значительно упрощает отладку компилятора, облегчает понимание кода, сгенерированного компилятором, но сжигает регистр, который в противном случае мог бы иметь общее назначение.
3
Обычно EBP используется для резервного копирования ESP, поэтому, если ESP изменен кодом в функции, все, что требуется для восстановления ESP, — это mov esp, ebp
. Поскольку EBP обычно остается неизменным в коде функции, его можно использовать для доступа к переданным параметрам или локальным переменным без необходимости корректировки смещений.
При использовании «фрейма стека» EBP помещается в стек в начале любой функции, поэтому значение EBP, помещаемое в стек, является значением EBP из функции, вызвавшей текущую функцию. Это позволяет коду или отладчику «обратно отслеживать» все случаи, когда EBP помещался в стек, и каждый экземпляр значения EBP в стеке можно было бы рассматривать как базовый указатель кадра стека.
Обратите внимание, что некоторые компиляторы имеют параметр «опустить указатели кадров», в этом случае EBP не используется для сохранения ESP или в качестве указателя кадра стека, что позволяет использовать EBP для переменной. Компилятор отслеживает ESP, и все локальные смещения являются смещениями от текущего значения ESP.
EBP и ESP — пережитки эпохи, когда компиляторы, например, не иметь статический анализ, чтобы определить, сколько байтов стека необходимо для вызова функции. Также стек должен был динамически увеличиваться и уменьшаться во время выполнения функции, прерывания позволяли бы уничтожить весь стек от 0 до SP, а спагетти-код был стандартом де-факто. На самом деле прерывания (и передача параметров только через регистры) были разработанным методом для вызова функций ядра.
В этом окружении один нуждается в , чтобы иметь фиксированную точку стека, где всегда находится адрес возврата вызывающему, локальные переменные и аргументы функции. Таким образом, регистр п.н.
был оправдан. В этой архитектуре bp
было разрешено индексировать ([bp — 300h]), а sp
— нет. Коды операций/инструкций, которые можно было интерпретировать как mov ax, [sp + 1111h]
, были повторно использованы для других целей.
В версии 386+ и с введением буквы «Е» ESP приобрело свойство смещения. В это время EBP
был освобожден от единственной цели, так как esp
мог справиться с обеими задачами.
Обратите внимание, что даже сейчас EBP
указывает на память через стек сегмент (SS), точно так же, как ESP
. Другие режимы адресации (без ESP/EBP в качестве основы) по умолчанию относятся к сегменту DS. (абсолютный, DI, SI и/или BX в 16-битном режиме и в 32-битном режиме адресации любой регистр может быть базовым в режиме адресации).
2
Регистр ESP является указателем стека для системного стека. Он редко изменяется непосредственно программой, но изменяется когда данные помещаются в стек или извлекаются из стека. Одно из применений стека — вызовы процедур. адрес инструкций, следующих за инструкцией вызова процедуры, хранится в стеке. указатели регистра EBP на базу. обычно единственный элемент данных, к которому осуществляется доступ в стеке, — это тот, который находится на вершине стека. Хотя регистр EBP часто используется для обозначения фиксированной точки в стеке, отличной от вершины стека, например, такими данными являются параметры. Они смещаются от вершины стека EBP к базовому указателю после адреса возврата. Итак, вы увидите что-то вроде EBP+0x8, EBP+0xC, это параметры как в 1 и 2 соответственно.
Понимание стека очень важно при программировании на языке ассемблера, поскольку это может повлиять на соглашения о вызовах, которые вы будете использовать независимо от типа. Например, даже cdecl или __stdcall тоже зависят от регистров ESP и EBP, а другие тоже каким-то образом зависят от каких-то регистров и стека.
1
Зарегистрируйтесь или войдите в систему
Зарегистрируйтесь с помощью Google
Зарегистрироваться через Facebook
Зарегистрируйтесь, используя электронную почту и пароль
Опубликовать как гость
Электронная почта
Требуется, но не отображается
Опубликовать как гость
Электронная почта
Требуется, но не отображается
Представительная ассамблея NEA удостоена награды ESP 2019 года
Автор: Тим Уокер 6 ИЮЛЯ 2019 ГОДА.
Мэтью Пауэлл, специалист года по поддержке образования 2019 года, вышел на сцену представительной ассамблеи NEA в субботу. Представляя его почти 7000 делегатам, собравшимся в конференц-центре Джорджа Э. Брауна в Хьюстоне, президент NEA Лили Эскельсен Гарсия похвалила Пауэлла за его «приверженность общественному образованию и нашим студентам».
«Технически у него есть должность надзирателя», — добавил Эскельсен Гарсия. «Но это только одна из многих шляп, которые носит этот талантливый человек».
Помимо своей работы надзирателем, Пауэлл также работает ночным сторожем и подменяет водителя автобуса, когда округу нужны подменные водители. Он работает в Центральной начальной школе округа Грейвс в Мэйфилде, штат Кентукки.
Пауэлл, который был назван ESP года на ежегодной национальной конференции NEA ESP в марте, является страстным сторонником обучения ребенка в целом — и за решающую роль, которую ESP играют в этом усилии. В своем выступлении перед RA Пауэлл подчеркнул непреходящее влияние каждого сотрудника школы на учащихся и их сообщество.
«В мой «класс» входят все 538 учеников моей школы, — сказал Пауэлл делегатам. «Мой класс находится в автобусе, в столовой, на игровой площадке, в холлах, у пруда с рыбками кои и во многих других местах вокруг школы».
В своей речи Пауэлл уделил внимание четырем педагогам — учителю, водителю автобуса, «обедительнице» и школьному сторожу, — которые повлияли на его взросление и помогли ему стать педагогом, которым он является сегодня.
«На самом деле эти педагоги создали атмосферу, в которой я чувствовал поддержку, питание и безопасность. Они создали среду, в которой я мог получать удовольствие и развиваться в школе. разница в моей жизни», — сказал Пауэлл.
Пауэлл рассказал, как в мае 2016 года торнадо пронесся по западному Кентукки, сравняв с землей большую часть округа Грейвс, где он преподает. В то время как его школу пощадили, Пауэлл и его коллеги начали действовать, чтобы помочь сообществу восстановиться, помогая доставлять предметы снабжения ученикам и их семьям.
Специалист года по поддержке образования 2019 года Мэтью Пауэлл @espunite делится своими 5 убеждениями, которые помогут всем его ученикам добиться успеха 👇 #NEARA19 pic.twitter.com/vAkICaiqtb
— Департамент качества NEA ESP (@NEArESPect) 6 июля 2019 г.
Делиться этой историей с делегатами не планировалось как «путешествие в прошлое», — сказал Пауэлл.
«Я хочу напомнить всем нам о том влиянии и силе, которые мы имеем в жизни наших учеников, в наших школах и в наших сообществах. Эта сила доступна каждому из нас, каждый день, в больших масштабах. и, казалось бы, в мелочах», — сказал он под аплодисменты делегатов.
Пауэлл, преданный политический активист государственных школ в Кентукки, упомянул о мощном союзе между учителями и ESP, разжигающем движение #RedForEd по всей стране.
«У ESP есть ценный опыт и знания, которые должны информировать наши школы о решениях, принимаемых в наших школах», — сказал Пауэлл. «Мы хорошо знаем наших студентов, и многие из нас живут в сообществе, где мы работаем … Мы заслуживаем места за каждым столом, где принимаются политики и решения, которые влияют на наших работ, наших студентов и наших сообществ, которые мы служим».
Пауэлл был ярым сторонником Закона о признании достижений классифицированных школьных служащих (RISE), который признает выдающийся вклад ESP и классифицированных школьных служащих в школах страны.
«Он установил первое в истории федеральное признание экстрасенсов», — сказал Пауэлл делегатам. «Это была победа, которая была бы невозможна без педагогов, которые обратились к членам Конгресса и поделились своим мнением. Это было удивительное достижение, но оно давно назрело».
Цитируя Хелен Келлер, Пауэлл призвал делегатов помнить, что «в одиночку мы можем сделать так мало; вместе мы можем сделать так много».
«Мы должны продолжать использовать наш коллективный голос и рассказывать наши истории, чтобы возвышать нашу профессию и требовать того, что нам нужно для наших студентов, — сказал Пауэлл в заключение.