Пример: Глобальная сеть INTERNET
Я ищу:
На главную  |  Добавить в избранное  

Главная/

Программирование, базы данных. /

Язык макроассемблера IBM PC

←предыдущая следующая→
... 2 3 4 5 6 7 8 9 10 11 12 

1.7.1 Стек

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

    Под стек можно отвести область в любом месте памяти. Размер ее мо­жет быть любым, но не должен превосходить 64Кб,  а ее  начальный адрес должен быть кратным 16.  Другими словами, эта область должна быть сег­ментом памяти;  он называется  сегментом стека.  Начало этого сегмента (первые 16 битов начального адреса)  должно  обязательно  храниться  в сегментном регистре SS.

    Хранимые в стеке элементы могут иметь любой размер, однако следует учитывать,  что в ПК  имеются  команды записи в стек  и чтения из него только слов.  Поэтому для записи байта в стек  его надо предварительно расширить до слова,  а запись  или  чтение двойных слов осуществляются парой команд.

    В ПК принято заполнять стек  снизу вверх,  от  больших  адресов  к меньшим:  первый элемент записывается в конец области,  отведенной под стек, второй элемент - в предыдущую ячейку области и т.д.  Считывается всегда элемент,  записанный в стек  последним.  В связи с этим  нижняя граница стека всегда фиксирована, а верхняя - меняется.  Слово памяти, в котором находится элемент стека,  записанный  последним,  называется вершиной стека.  Адрес вершины,  отсчитанный от начала сегмента стека, обязан находиться в указателе стека - регистре SP.  Таким образом, аб­солютный адрес вершины стека определяется парой SS:SP.

          -----                 -----                 -----

  SS:SP   |   |           SS:SP  |   |           SS:SP  |   |

    |     -----   запись    |   -----   чтение    |   -----

    |     |   |  =======>   ---->| b |  =======>   |  |   |

    |     -----   в стек        -----  из стека   |   -----

    ----->| a |                 | a |             ---->| a |

          -----                 -----                 -----

    Значение 0 в регистре SP свидетельствует о том, что стек полностью заполнен  (его вершина "дошла"  до начала области стека).  Поэтому для

контроля за переполнением стека надо перед новой записью в стек прове­рять условие SP=0 (сам ПК этого не делает). Для пустого стека значение SP должно равняться размеру стека, т.е. пара SS:SP должна указывать на байт, следующий за последним байтом области стека. Контроль за чтением из пустого стека, если надо, обязана делать сама программа.

    Начальная установка регистров SS и SP может быть произведена в са­мой программе,  однако в MASM предусмотрена возможность автоматической загрузки этих регистров. Если в директиве SEGMENT, начинающей описание сегмента стека, указать параметр STACK,  тогда ассемблер  (точнее, за­грузчик) перед тем, как передать управление на первую команду машинной программы, загрузит в регистры SS и SP нужные значения. Например, если в программе сегмент стека описан следующим образом:

       ST SEGMENT STACK

          DB   256 DUP(?)    ;размер стека - 256 байтов

       ST ENDS

и  если под этот сегмент была выделена область памяти  начиная с абсо­лютного адреса 12340h,  тогда к началу выполнения программы в регистре SS окажется величина  1234h,  а в регистре SP  - величина 100h (=256). Отметим, что эти значения соответствуют пустому стеку.

         1.7.2 Основные стековые команды

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

        Запись слова в стек:  PUSH op

Здесь op обозначает  любой 16-битовый регистр  (в том числе и сегмент­ный)  или  адрес слова памяти.  По этой команде  значение  регистра SP уменьшается на 2  (вычитание  происходит по модулю  2^16),  после чего указанное операндом слово записывается в cтек по адресу SS:SP.

        Чтение слова из стека:  POP op

Слово, считанное из вершины стека, присваивается операнду op  (регист­ру, в том числе сегментному, но не CS,  или слову памяти),  после чего значение SP увеличивается на 2.

         Переход с возвратом: CALL op

Эта команда записывает адрес следующей за ней команды в стек  и  затем делает переход по адресу, определяемому операндом op. Она используется для переходов на подпрограммы с запоминанием в стеке адреса возврата.

Имеются следующие разновидности этой команды (они аналогичны вари-

антам команды безусловного перехода JMP):

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

    - внутрисегментный абсолютный косвенный переход  (op - адрес слова памяти, в которой находится адрес (смещение) той команды, на которую и будет сделан переход); и здесь в стек записывается только смещение ад­реса возврата;

    - межсегментный абсолютный прямой переход  (op -  непосредственный операнд вида seg:ofs,  а в MASM - это FAR PTR <метка>  или имя дальней процедуры (см. ниже)); здесь в стек заносится текущие значение регист­ров CS и IP  (первым в стек записывается содержимое CS), т.е. абсолют­ный адрес возврата, после чего меняются регистры CS и IP;

    - межсегментный абсолютный косвенный переход  (op - адрес двойного слова, в котором находится пара seg:ofs, задающая абсолютный адрес пе­рехода); и здесь в стеке спасается содержимое регистров CS и IP.

        Переход (возврат) по адресу из стека:  RET op

Из стека считывается адрес и по нему производится переход. Если указан операнд (а это должно быть неотрицательное число), то после чтения ад­реса стек еще очищается на это число байтов (к SP добавляется это чис­ло).  Команда используется для возврата из подпрограммы по адресу, за­писанному в стек по команде CALL  при вызове подпрограммы,  и одновре­менной очистки стека от параметров, которые основная программа занесла

в стек перед обращением к подпрограмме.

    Команда RET имеет две разновидности  (хотя в MASM они записываются и одинаково):  в одном случае из стека считывается только одно слово ­смещение адреса возврата, а во втором - из стека считывается пара seg: ofs, указывающая абсолютный адрес возврата.  Как ассемблер определяет, какой из этих двух случаев имеет место, объяснено ниже.

     В ПК стек  в основном  используется для организации подпрограмм и прерываний.  Подпрограммы рассматриваются ниже, а прерывания - в главе 3. Однако, даже если программе не нужен стек, она все равно должна от­вести под него место. Дело в том, что стеком будет неявно пользоваться операционная система при обработке прерываний, которые возникают (нап­ример, при нажатии клавиш на клавиатуре) в то время, когда выполняется программа. Для нужд ОС рекомендуется выделять в стеке 64 байта.

         1.7.3 Подпрограммы

    Типичная схема огранизации подпрограмм, обычно используемая транс­ляторами с языков высокого уровня для реализации процедур и функций (в частности, рекурсивных), следующая.

    При обращении к подпрограмме  в стек заносятся параметры для нее и адрес возрата, после чего делается переход на ее начало:

       PUSH param1   ;запись 1-го параметра в стек

       ...

PUSH paramk   ;запись последнего (k-го) параметра в стек

       CALL subr    ;переход в возратом на подпрограмму

(Замечание: если необходимо вычислить параметр или если его размер от­личен

←предыдущая следующая→
... 2 3 4 5 6 7 8 9 10 11 12 


Copyright © 2005—2007 «RefStore.Ru»