Реализация вложенных процедур
Возникает вопрос: как же программа, находясь в конкретной точке своего выполнения, может отслеживать то, какие области инициализации ей доступны? Это делается с помощью структуры данных называемой дисплеем. Дисплей содержит указатели на самую последнюю область текущего блока и на области инициализации всех блоков, объемлющих данный блок в программе. Например, если в программе А была вызвана сначала процедура В, а затем С, то дисплей содержит указатели на области инициализации А В и С (рис. 3.2).
Рис. 3.2. Соответствие содержимого дисплея области инициализации после вызова процедур В и С
Если после этого вызвать процедуру D (в то время как В и С еще не завершены), то картина изменится (рис. 3.3).
Рис. 3.3. Соответствие содержимого дисплея области инициализации после вызова процедуры D
После того как некоторый блок (процедура) завершает свою работу, его область инициализации удаляется из памяти (стека) и одновременно соответствующим образом корректируется дисплей.
Большинство языков высокого уровня хранит локальные данные блоков в стеке. Эти переменные называют еще автоматическими, или динамическими. Память для них резервируется путем уменьшения значения регистра-указателя стека ESP/SP на величину, равную длине области, занимаемой этими динамическими переменными. Доступ к этим переменным осуществляется посредством регистра ЕВР/ВР. Если один блок вложен в другой, то для его динамических (локальных) переменных также выделяется место (кадр) в стеке, но в этот кадр помещается указатель на кадр стека для включающего его блока. Команды ENTER и LEAVE как раз и позволяют поддержать в языке ассемблера принципы работы с переменными блоков, как в блочно-структурированных языках. Дисплей организуется с помощью второго операнда команды ENTER и стека.
Например, в начале работы главной процедуры А и после вызова процедуры В кадр стека будет выглядеть так, как показано на рис. 3.4.
Рис. 3.4. Кадр стека после вызова процедур А и В
Из рисунков видно, что, используя дисплей, мы фактически имеем адреса областей инициализации, доступных по признаку вложенности объемлющих блоков. Обратный процесс завершения работы с блоками и удаления соответствующих областей инициализации поддерживается командой LEAVE.