5.3.2. Вложенные процедуры с дисплеями

Процедурам можно передавать не только адрес одной вышерасположенной активизационной записи, но и набор адресов сразу для всех уровней вложеннос­ти - от нулевого до более высокого. При этом доступ к любой нелокальной про­цедуре сводится всего к двум командам, а перед вызовом процедуры вообще требуется каких-либо дополнительных действий (так как вызываемая процедура

поддерживает дисплей самостоятельно).

proc_at_3 proc

push bp

mov bp.sp

near

Сохранить динамическую ссылку. Установить адрес текущей записи.ттшш

Сложные приемы программирования

push

display[6]

Сохранить предыдущее значение адреса третьего уровня в дисплее.

raov

sub sp,N [..J

display[6],bp

Инициализировать третий уровень в дисплее. Выделить место для локальных переменных.

mov

mov bx,display[4] ax,ss:[bx-6]

Получить адрес записи для уровня 2. Считать значение второй переменной из уровня 2.

[...] add

sp,n display[6]

Освободить стек от локальных переменных.

Восстановить старое

значение третьего уровня в дисплее.

pop

pop ret bp

proc_at_3

endp

Здесь считается, что в сегменте данных определен массив слов display, имею­щий адреса последних использованных активизационных записей для каждого уровня вложенности: display[0] содержит адрес активизационной записи нулево­го уровня, display[2] - первого уровня и так далее (для близких адресов).

Команды ENTER и LEAVE можно использовать для организации вложеннос­ти с дисплеями, но в такой реализации дисплей располагается не в сегменте дан­ных, а в стеке, и при вызове каждой процедуры создается его локальная копия.

;  enter N,4 (уровень вложенности 4,  N байтов на стековый кадр) эквивалентно набору команд

push

bp

;  Адрес записи третьего уровня.

push

[bp-2]

 

push

'[bp-4]

 

push

[bp-6]

 

push

[bp-8]

;  Скопировать дисплей.

mov

bp, sp

;

add

bp, a

;   ВР = адрес начала дисплея текущей записи

sub

sp,N

;   Выделить кадр для локальных переменных.

Очевидно, что такой метод оказывается крайне неэффективным с точки зре­ния как скорости выполнения программы, так и расходования памяти. Более того, команда ENTER выполняется дольше, чем соответствующий набор простых ко­манд. Тем не менее существуют ситуации, когда может потребоваться создание локальной копии дисплея для каждой процедуры. Например, если процедура, адрес которой передан как параметр другой процедуре, вызывающейся рекурсив­но, должна обращаться к нелокальным переменным. Но и в этом случае передачи всего дисплея через стек можно избежать - более эффективным методом оказы­ваются простые статические ссылки, рассмотренные ранее.