2) копирует в регистр BP или EBP значение указателя стека, которое становится базовым адресом стекового кадра;
3) уменьшает значение указателя стека на значение первого операнда команды, чем резервирует место под локальные переменные.
Перечисленные действия эквивалентны такой последовательности команд:
PUSH EBP
MOV EBP, ESP
SUB ESP, размер
В общем случае команда работает как указано, но после первого действия в стек последовательно записываются адреса стековых фреймов всех процедур предыдущего уровня, что позволяет при необходимости легко обратиться к их локальным переменным.
Пример. Пусть процедура A имеет уровень вложенности 0. Тогда после выполнения команды
ENTER 1024, 0
стек будет иметь следующий вид:
старое значение EBP |
←EBP |
место |
|
для локальных данных |
|
процедуры A (1 Кб) |
←ESP |
Пусть, далее, процедура B имеет уровень вложенности 1 и вызывается из процедуры A. Тогда после выполнения в процедуре B команды
ENTER 16, 1
стек будет иметь следующий вид:
старое значение EBP |
|
место |
|
для локальных данных |
|
процедуры A (1 Кб) |
|
значение EBP
до вызова команды |
←EBP |
EBP для процедуры A |
|
место |
|
для локальных данных |
|
процедуры B (16 б) |
←ESP |
LEAVE выход из процедуры 80186
Выполняет действия, противоположные команде ENTER
. Фактически, команда выполняет следующие
действия:
1)
копирует содержимое EBP в
ESP, тем самым выбрасывая из стека весь кадр, созданный
последней выполненной командой ENTER
,
кроме значения EBP до вызова команды ENTER
;
2)
загружает из стека EBP для предыдущей процедуры,
что одновременно восстанавливает значение регистра ESP,
который последний имел до последнего вызова команды ENTER
.
Перечисленные действия эквивалентны следующей последовательности команд:
MOV ESP, EBP
POP EBP
Примечание. Стековые кадры ненулевого уровня редко используются непосредственно при программировании на языке ассемблера из-за сложности вручную отслеживать уровни вложенности процедур. Они используются, во-первых, трансляторами языков высокого уровня, а во-вторых, ассемблерами при использовании встроенных макросов для вызова процедур.
8.1. Сегменты
8.2. Процедуры
Каждая программа, на каком бы языке она ни была написана, состоит из одного или нескольких сегментов. Сегмент суть непрерывная область памяти определённого назначения.
Как уже говорилось, в типичной программе бывают сегменты трёх типов:
— кода, содержащие команды;
— данных, содержащие данные;
— стека, содержащие стек.
Разумеется, ассемблер позволяет как угодно изменять устройство программы — помещать данные в сегмент кода, разносить код на несколько сегментов, объединять различные сегменты и тому подобное.
Сегмент программы описывается директивами SEGMENT и ENDS:
имя_сегмента SEGMENT [READONLY] выравнивание тип \ разрядность′
класс′
; содержимое сегмента
имя_сегмента ENDS
Имя сегмента — идентификатор, который используется для получения адреса сегмента, а также для объединения сегментов в группы, если это необходимо.
READONLY
— необязательное
ключевое слово. Если оно присутствует, MASM выдаёт
сообщение об ошибке на все команды, непосредственно выполняющие запись в данный
сегмент. Другие ассемблеры этот операнд игнорируют.
Выравнивание указывает транслятору и компоновщику, с какого адреса может начинаться сегмент. Ассемблеры MASM, TASM и WASM допускают следующие значения данного операнда:
BYTE
— с любого адреса;
WORD
— с адреса,
кратного 2;
DWORD
— с адреса,
кратного 4;
PARA
— с адреса,
кратного 16
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.