Стек. Подпрограммы

 

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

Во многих случаях программе требуется временно запомнить информацию, а затем считывать ее в обратном порядке. Эта проблема в ПК решена посредством реализации стека LIFO ("последний пришел - первый ушел"), называемого также стеком включения/извлечения (stack - кипа, например, бумаг). Наиболее важное использование стека связано с процедурами. Стек обычно рассчитан на косвенную адресацию через регистр SP - указатель стека. При включении элементов в стек производится автоматический декремент указателя стека, а при извлечении - инкремент, то есть стек всегда "растет" в сторону меньших адресов памяти. Адрес последнего включенного в стек элемента называется вершиной стека (TOS).

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

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

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

 

 

Значение 0 в регистре SP свидетельствует о том, что стек полностью заполнен  (его вершина "дошла"  до начала области стека).  Поэтому для контроля за переполнением стека надо перед новой записью в стек проверять условие SP=0 (сам I80Х86 этого не делает). Для пустого стека значение 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).

Отметим, что эти значения соответствуют пустому стеку.

 

 

К оглавлению

Назад к разделу "Строковые операции"

Вперед к разделу "Основные стековые команды"