На главную
Подписка
Новости










Главная / MS-DOS / MS-DOS. РУКОВОДСТВО РАЗРАБОТЧИКА / Глава 2 / Инструкции ENTER и LEAVE для локальной памяти стека Сделать домашней страницей Добавить в избранное Написать писмо

НАЗАД СОДЕРЖАНИЕ ВПЕРЁД

Инструкции ENTER и LEAVE для локальной памяти стека

В более старших моделях семейства микропроцессоров 8086 фирмы "Интел" обеспечены две новые инструкции для помощи при использовании локальной памяти в стеке. Все процессоры iAPX186, iAPX188 и iAPX286 поддерживают инструкции ENTER (вход) и LEAVE (выход). Инструкция ENTER используется для установки локальной памяти в стеке, когда программа вводится впервые, а инструкция LEAVE освобождает эту локальную память, когда программа осуществляет выход. Дополнительные инструкции ENTER и LEAVE имеют возможность поддержки указателей блоков, которые используются определенным блоком структурированного языка высокого уровня, например, такого, как язык программирования Паскаль.


В связи со сложностью этих инструкций, здесь представлены их макросы, эквивалентные листингу 2-9. Это позволит пользователям микропроцессоров 8086/8088 прочувствовать преимущество этих инструкций при переходе к более современному микропроцессору. Обратите внимание на то, что макросы enter и leave отклоняются от неофициального стандарта отсутствием в качестве префикса знака @, потому что они предназначены для замены инструкций ENTER и LEAVE при использовании микропроцессоров 8086/8088.


При выполнении инструкция ENTER осуществляет в стеке три действия. Она всегда помещает значение регистра BP в стек. Если значение level (уровень) больше или равно 1, то инструкция копирует предыдущие значения регистра BP в стек. Если значение local (локальный) больше или равно 1, то инструкция открывает пространство для локальной памяти в стеке путем вычитания значения local из старого BP в стеке (первая инструкция push).



          Старшие адреса .----------------------------------.-----
                         | Предыдущие структуры Stackframe  |   ^
                         |----------------------------------|   |
                         |             Param3               |   |
                  [BP+8] |----------------------------------|   |
                         |             Param2               |   |
                  [BP+6] |----------------------------------|   |
                         |             Param1               |   |
                  [BP+4] |----------------------------------|   |
                         |                                  |   |
                  [BP+2] |----------------------------------|   |
                         |             XamplBP              |Stackframe
                  [BP+0] |----------------------------------|   |
                         |             LocIndx              |   |
                  [BP-2] |----------------------------------|   |
                         |             LocChar              |   |
                  [BP-4] |----------------------------------|   |
                         |/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\|   |
                                                                |
                          /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\    |
                  [BP-16]|----------------------------------|   |
                         |             LocWord              |   v
                  [BP-18]|----------------------------------|-----
                         |      Сохраненное значение SI     |
                         |----------------------------------|
                         |      Сохраненное значение DI     |
           Вершина стека |----------------------------------|
                         |          Доступная память        |
          Младшие адреса  ----------------------------------

               Рис.2-1. Локальная память стека и доступ к параметрам

Инструкция LEAVE выполняет действия, обратные действиям инструкции ENTER, пока регистр BP оставлен в, или сброшен в первоначальное значение, установленное инструкцией ENTER.


Наиболее запутанной фазой этой операции является ее связь с указателем блока данных. На рис.2-2 показано состояние (и содержимое) стека для ряда операций, которые состоят из четырех последовательных инструкций ENTER.


Каждый элемент стека на рис.2-2 отображает в символической форме 2 байта (по этой причине все значения параметров local (локальный) для инструкции ENTER умножаются на 2 байта. Это не является ограничением инструкции ENTER). Стрелки на рис. 2-2 в символической форме отображают ссылку одного элемента на другой элемент (т.е. элемент содержит адрес другого элемента).



              ENTER 4,1           ENTER 2,2           ENTER 4,3
              xxxxxxxx            xxxxxxxx            xxxxxxxx
          .-->[старое BP]<---BP#1 [старое BP]         [старое BP]
          ----[FP # 1   ]  ^      [FP # 1   ]         [FP # 1   ]
              [local    ]  |      [local    ]         [local    ]
         SP-->[local    ]  |      [local    ]         [local    ]
                           |  .-->[BP # 1   ]<---BP#2 [старое BP]
                            --|---[FP # 1   ]  ^      [FP # 1   ]
                               ---[FP # 2   ]  |      [FP # 2   ]
                            SP--->[local    ]  |      [local    ]
                                               |  .-->[BP # 2   ]<--BP#3
                                               |  |   [FP # 1   ]
                                                --|---[FP # 2   ]
                                                   ---[FP # 3   ]
                                                      [local    ]
                                                 SP-->[local    ]

                    Рис.2-2. Действие инструкции ENTER в стеке

Первая инструкция ENTER (уровень 1) устанавливает единственный указатель блока данных, указывающий на свой собственный блок данных, и открывает верхнее пространство в стеке для 4 байтов памяти. Вторая инструкция ENTER (уровень 2) не только создает свой собственный указатель блока (FP#2), но и копирует указатель блока данных из предыдущего блока данных (FP#1). Вторая инструкция ENTER создает только 2 байта локальной памяти. Последняя инструкция ENTER (уровень 3) переносит шаг 1 операции дальше, копируя указатели блока предыдущих двух уровней (FP#1 и FP#2).


Почему выполнение примера последовательно начинается с уровня 1 инструкции ENTER, а не с инструкции ENTER уровня 0? Уровень 0 инструкции ENTER просто помещает содержимое регистра BP в стек и вычитает значение local (локальный) из указателя стека, устанавливая регистр BP для указания на только что помещенное значение регистра BP. Указатели блока данных не копируются. Уровень 0 инструкции ENTER является идеальным для создания локальной памяти в стеке. При использовании инструкции ENTER вместе с директивой STRUC, инструкция ENTER может почти автоматически создавать локальную память стека, которая легко доступна.



                 Листинг 2-9. Эквиваленты макросов для инструкций
                                   ENTER и LEAVE
         -----------------------------------------------------------------
         ;; МАКРООПРЕДЕЛЕНИЯ ДЛЯ ИНСТРУКЦИЙ ENTER И LEAVE
         ;;
         ;; Описания базовой адресации для использования при доступе
         ;; к элементам в блоке стека, созданном инструкцией ENTER
         ;;
         pbase equ     [BP + 4]           ;; доступ к параметрам
         lbase equ     [BP - ??tsize]     ;; доступ к локальным данным
         fbase equ     [BP - ??fsize]     ;; доступ к указателю блока
         ;; Form  ENTER     local , level 
         ;;
         ;; ENTER-- Создание блока стека и распределение локальной памяти
         ;; Копирование указателя блока стека из предыдущей программы в
         ;; новый блок стека для этой программы и открытие пространства
         ;; в стеке для новой локальной памяти
         ;;
         enter  MACRO   local,level
                ??tsize = local + level * 2
                ??fsize = level * 2
                push    bp
                IF (level NE 0)
                  IF (level GT 1)
                    REPT level - 1
                      sub       bp,2
                      push      [bp]
                    ENDM
                  ENDIF
                    mov bp,sp
                  IF (level GT 1)
                    add bp,(level - 1) * 2
                  ENDIF
                  push bp
                ELSE
                  mov   bp,sp
                ENDIF
                sub     sp,local
                ENDM
         ;; Form LEAVE
         ;;
         ;; LEAVE-- Выполнение процедуры возврата, удаляющей блок стека
         ;; и локальной памяти, установленной по инструкции ENTER
         ;;
         leave  MACRO
                mov    sp,bp
                pop    bp
                ENDM
         -----------------------------------------------------------------

На листинге 2-10 показан фрагмент программы создания локальной памяти в стеке с использованием инструкции ENTER. Этот фрагмент программы определяет, распределяет и использует локальную память из стека. Инструкция ENTER способствует обучению резервирования необходимого количества памяти благодаря оператору MASM SIZE. Знак процента (%) требуется только с реализацией макроса инструкции ENTER. При использовании версии машинной программы (поддерживаемой макроассемблером MASM 2.0 и выше путем указания переключателя .286С) знак процента(%) должен быть опущен.



             Листинг 2-10. Создание и ссылка к локальной памяти стека
                                по инструкции ENTER
         -----------------------------------------------------------------

         ?data_1      STRUC
         my_var dw    ?
         ?data_1      ENDS
         test   PROC  NEAR
                ENTER %(size ?data_1),0  ; распределение локальной памяти
                mov   lbase.my_var,10    ; запоминание значения в л.п.
         -----------------------------------------------------------------

Символ lbase в листинге 2-9 определен как базовый адрес для доступа ко всем локальным переменным. Действительной ссылкой, создаваемой в инструкции MOV, является:



                          mov   [BP - ??tsize].my_var,10

Символ ??tsize устанавливается реализацией макроса инструкции ENTER в количества байтов, добавляемых в стек по инструкции ENTER, не включая значение регистра BP. Значение этого символа вычисляется как local + level * 2. При вычитании значения символа ??tsize из содержимого регистра BP, результатом является адрес верхней части стека. Таким образом, все ссылки структуры имеют положительное смещение от символа lbase. Даже если используется версия машинного кода инструкции ENTER, можно легко написать макрос, который вычисляет значение символа ??tsize и создает инструкцию ENTER таким образом, что этот механизм может быть с успехом использован на процессорах 186/188/286.


Другим символом, определенным в листинге 2-9, является символ pbase - базовый адрес для доступа ко всем переменным, переданным в стек. Значение символа pbase равно [BP + 4], чтобы охватить 2 байта, помещенные в стек как часть near (близкий) инструкции CALL (вызвать процедуру) и 2 байта, требующиеся для регистра BP, помещенного в стек по инструкции ENTER. После того, как определена структура параметров стека, символ pbase можно использовать по имени его поля для символического доступа к данным, например, pbase.my_param.


Получив описание простого использования инструкции ENTER, вернемся к вопросу об указателях блока данных. Что это такое? Каждый указатель блока данных указывает на начало блоков данных предыдущей программы стека. Путем загрузки регистра BP содержимым одного из указателей блока данных, размещенного в текущем блоке, может быть получен доступ к локальным переменным предыдущего уровня. Первоначально это было спроектировано для реализации языков программирования высокого уровня таких как, например, Паскаль, где программа имеет автоматический доступ к переменным порождающей программы. Если читатель недостаточно созрел в отношении высокого уровня структурного программирования на языке Ассемблер, то он вероятно пропустит использование возможностей указателя блока инструкции ENTER. Во всяком случае, если читатель решил испробовать использование инструкции ENTER с указателем блока, то незначительные эксперименты дадут ему возможность прочувствовать ее функционирование.


НАЗАД СОДЕРЖАНИЕ ВПЕРЁД

Hosted by uCoz