[Назад] [Далее]

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

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

proc_at_3    proc       near
             push       bp            ; сохранить динамическую ссылку
             mov        bp,sp         ; установить адрес текущей записи
             push       display[6]    ; сохранить предыдущее
                                      ; значение адреса третьего
                                      ; уровня в дисплее
             mov        display[6],bp ; инициализировать третий
                                      ; уровень в дисплее
             sub        sp,N          ; выделить место для
                                      ; локальных переменных
             [...]
             mov        bx,display[4] ; получить адрес записи для уровня 2
             mov        ax,ss:[bx-6]  ; считать значение второй
                                      ; переменной из уровня 2
             [...]
             add        sp,N          ; освободить стек от
                                      ; локальных перееденных
             pop        display[6]    ; восстановить старое
                                      ; значение третьего уровня в дисплее
             pop        bp
             ret
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,8     ; BP = адрес начала дисплея текущей записи
             sub       sp,N     ; выделить кадр для локальных переменных

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


п»ї
"target=_blank><\/a>") //-->