Начинающая обучаемая сборка, сохраняющая esp после вызова функции - PullRequest
3 голосов
/ 12 марта 2010

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

mov esi, esp
sub esp, 12 // on 32bit OS this would mean that there are 3 arguments to the function
// push, function call etc
cmp esi, esp // should be the same

или

mov esi, esp
// push, function call etc
add esp, 12
cmp esi, esp // should be the same

Также, если по какой-то причине происходит сбой cmp, безопасно ли выполнять mov esp, esi для повторного выравнивания стека?

Спасибо

РЕДАКТИРОВАТЬ: Кроме того, почему мне нужно сделать это для вызова, как sprintf, но MessageBox, кажется, исправить ESP для меня? Как мне узнать, какая функция нуждается в этом, а какая нет?

Ответы [ 2 ]

4 голосов
/ 12 марта 2010

Да, важно получить правильный знак при использовании esp (в этом случае вычитание, но иногда вам нужно добавить при ссылке на что-то уже в стеке, например, аргументы внутри функции). Причиной этого является то, что в памяти размер стека увеличивается на вниз . Это противоречит тому, как мы обычно думаем о стеке (вы помещаете вещи сверху и удаляете их сверху), в памяти это будет все выше и выше адреса по мере роста стак k. Но стек вызовов на процессорах X86 (и большинстве других) на самом деле растет вниз. Это похоже на добавление пластин к нижней части стека и удаление их из нижней части ... в памяти адреса становятся все ниже и ниже по мере добавления новых элементов в стек.

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

Разница между sprint и MessageBox заключается в «соглашении о вызовах». Это говорит языкам более высокого уровня (C), как обрабатывать кадр стека и регистрировать, когда они вызываются. sprintf это cdecl , а MessageBox это stdcall .

1 голос
/ 12 марта 2010

Кроме того, почему мне нужно сделать это для вызова типа sprintf, но MessageBox, кажется, исправляет ESP для меня?

Это потому, что функция MessageBox() удаляет параметры из стека при возврате. Это можно сделать, потому что количество параметров фиксировано.

Однако функция sprintf() вызывается с переменным числом параметров. Функция не знает, сколько вызывающих абонентов поместили в стек, поэтому вызывающий обязан очистить их при возврате вызова.

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