Реализация вложенных процедур
Понятие вложенной процедуры включает в себя возможность описания процедур внутри друг друга, при этом каждая из процедур может иметь локальные данные, видимые для вложенных в нее процедур, но не видимые для процедур, находящихся на одном уровне вложенности с данной процедурой. Для организации такой вложенности существуют две возможности – организация средствами ассемблера и определенная самим пользователем. Рассмотрим первую из них. Для нее требуются команды ассемблера ENTER и LEAVE. Их формат приведен ниже.
Команда enter loc_size.lexjev – ENTER (setup parameter block for ENTERing procedure) – реализует установку кадра стека для параметров процедуры. Работа команды заключается в следующем.
- Размещение текущего значения регистра ЕВР/ВР в стеке.
- Сохранение текущего значения ESP/SP в промежуточной переменной FP (имя переменной выбрано случайно).
- Если лексический уровень вложенности (операнд lexlev) не равен нулю, то (lex_lev-l) сделать следующее:
- в зависимости от установленного режима адресации usel6 или use32
- выполнить вычитание (ВР-2) или (ЕВР-4) и записать результат обратно в ЕВР/ВР;
- сохранить значение ЕВР/ВР в стеке;
- сохранить в стеке значение промежуточной переменной fp.
- Запись значения промежуточной переменной fp в регистр ЕВР/ВР.
- Уменьшение значения регистра ESP/SP на величину, заданную первым операндом, минус размер области локальных переменных locsize: ESP/SP= (ESP/SP)-loc size.
Команда LEAVE (LEAVE from procedure – выход из процедуры) не имеет операндов и выполняет удаление из стека области локальных (динамических) переменных, выделенной командой ENTER. Команда выполняет обратные команде ENTER действия.
- Содержимое ebp/bp копируется в ESP/SP, тем самым восстанавливается значение ESP/SP, которое было до вызова данной процедуры. С другой стороны, восстановление старого значения ESP/SP означает освобождение пространства в стеке, отведенного для завершающейся процедуры (локальные переменные процедуры уничтожаются).
- Из стека восстанавливается содержимое ЕВР/ВР, которое было до входа в процедуру. После этого действия значение ESP/SP также становится таким, каким оно было до входа в процедуру.
В результате этих двух действий также восстанавливается кадр стека, если он был, вызывающей программы.
Команды ENTER и LEAVE специально введены в систему команд микропроцессора для поддержки вложенных процедур, как это делают для блочно-структурированных языков высокого уровня типа Паскаль или С. В этих языках программа разбивается на блоки. В блоках можно описать свои собственные (локальные) идентификаторы, которые не могут быть использованы вне этого блока. К примеру, на рис. 3.1 в виде блоков изображена структура некоторой программы.
Рис. 3.1. Изображение структуры некоторой программы в виде блоков
В правом верхнем углу каждого блока (процедуры) стоит номер лексического уровня вложенности этого блока относительно других блоков программы. Большинство блочно-структурированных языков в качестве основного метода распределения памяти для переменных в блоках используют автоматическое распределение памяти. Это означает, что при входе в блок (вызове процедуры и т. п.) в некотором месте оперативной памяти (или в стеке) выделяется область памяти для переменных этого блока (ее можно назвать областью инициализации). После выхода из этого блока связь программы с этой областью теряется, то есть эти переменные становятся недоступными. Но если, как в нашем примере, в этой Процедуре есть вложенные блоки (процедуры), то для некоторого внутреннего блока (например, С) могут быть доступны области инициализации (переменные) блоков, объемлющих данный блок. В нашем примере для блока С доступны также переменные блоков В и А, но не D.