Главная

Популярная публикация

Научная публикация

Случайная публикация

Обратная связь

ТОР 5 статей:

Методические подходы к анализу финансового состояния предприятия

Проблема периодизации русской литературы ХХ века. Краткая характеристика второй половины ХХ века

Ценовые и неценовые факторы

Характеристика шлифовальных кругов и ее маркировка

Служебные части речи. Предлог. Союз. Частицы

КАТЕГОРИИ:






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




Стек представляет собой непрерывный блок оперативной памяти, доступ к которому осуществляется посредством пары регистров SS и ESP. В регистре ESP хранится смещение вершины стека (то есть адрес последнего добавленного элемента). Значение ESP изменяется такими командами, как push, pop, call, ret и др. Напрямую изменять ESP программисту обычно не требуется. Стек в программе используется, во-первых, как удобное место для временного сохранения значений регистров. Во-вторых, при вызове процедуры в стек помещаются её аргументы, адрес возврата, в нём же выделяется память под локальные переменные. Для помещения значения в стек используется команда push. При вставке 4-байтового числа она вначале вычитает 4 из ESP (стек растёт в сторону уменьшения адресов), после чего по полученному адресу записывает аргумент. Пример вызова: push eax. Для извлечения аргумента из стека применяется команда pop – она выполняет обратные действия. Также имеются команды pushad и popad, позволяющие поместить и извлечь из стека сразу все 32-разрядные регистры общего назначения. Особенности написания и вызова процедур.

Пример:

.model flat, stdcall

sample PROC uses eax ebx, a:DWORD, b:DWORD

LOCAL tmp1:DWORD, tmp2:DWORD

;...

ret

sample ENDP

В данном примере создана процедура sample. У неё имеются два аргумента a и b, оба типа DWORD. С помощью директивы uses мы указали, что в процедуре изменяются значения регистров eax и ebx – в результате ассемблер сгенерирует код, который при входе в процедуру сохранит эти регистры в стеке, а перед выходом восстановит. В процедуре имеются две локальных переменных tmp1 и tmp2 типа DWORD. Выход из процедуры выполняется командой ret. Данную процедуру можно вызвать командой: INVOKE sample, arg1, arg2 Рассмотрим, что будет находиться в стеке во время выполнения процедуры (стек растёт в сторону уменьшения адресов – на рисунке это будет сверху вниз).

  arg2 [EBP+12]
  arg1 [EBP+8]
  Адрес возврата [EBP+4]
  старое значение EBP ←EBP
  tmp1 [EBP-4]
  tmp2 [EBP-8]
  старое значание eax [EBP-12]
ESP→ старое значение ebx [EBP-16]

В начале процедуры ассемблер вставляет примерно следующий код:

push ebp; сохраним текущее значение ebp

mov ebp, esp; запоминаем текущую позицию в стеке

sub esp, 8; место под локальные переменные

push eax;сохраняем указанные в uses регистры

push ebx

В конце процедуры ассемблер вставляет примерно такой код:

mov esp, ebp;восстанавливаем положение в стеке на момент начала процедуры

pop ebp

ret 8; выходим, извлекая 8 байтов аргументов

Из данного рисунка и примеров кода видно, что для доступа к аргументам и локальным переменным используется косвенная адресация со смещением относительно регистра EBP. Хотя мы для удобства можем использовать осмысленные имена наподобие arg1 или tmp2, в итоге они преобразуются ассемблером в обращение к памяти, адресуемой EBP. Директива INVOKE для вызова процедуры транслируется примерно в следующую последовательность команд:

push arg2

push arg1

call sample

 






Не нашли, что искали? Воспользуйтесь поиском:

vikidalka.ru - 2015-2024 год. Все права принадлежат их авторам! Нарушение авторских прав | Нарушение персональных данных