Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Учебное пособие 3000239.doc
Скачиваний:
23
Добавлен:
30.04.2022
Размер:
1.12 Mб
Скачать

6.3. Приемы работы со стеком

Прежде всего, следует отметить общее правило работы со стеком: если мы что-то записали в стек, то обычно именно мы и обязаны все это считать из стека. Иначе при работе со стеком возможны семантические ошибки в работе программы.

Сохранение значений регистров

Очень часто стек используется для временного хранения значений регистров. Если надо сохранить текущее значение какого-нибудь регистра, скажем СХ, и в то же время этот регистр нам нужен для иных целей, тогда можно поступить так: надо спасти в стеке значение регистра, затем использовать регистр как нужно, а в конце восстановить прежнее значение регистра, считав его из стека:

PUSH СХ

… ;использование СХ

POР СХ

Пересылка данных через стек

Стек нередко используется для пересылки какой-то величины из одной ячейки памяти в другую, когда не хотят портить содержимое регистров. Например, выполнить присваивание X:=Y, где X и Y – переменные размером в слово, можно так:

PUSH Y

POP X ;X:=Y

Проверка на выход за пределы стека

Следует понимать, что команды PUSH и POP не осуществляют проверку на выход за пределы стека. Например, если стек пуст и применяется команда чтения из стека, то ошибка не будет зафиксирована (будет считано слово, следующее за сегментом стека). Аналогично, не будет зафиксирована ошибка, если мы записываем в стек, когда он уже полон. Такие проверки, если надо, обязан делать сам программист. Делаются же эти проверки очень просто:

SP=0? – стек полон?

SP=k? – стек пуст? (k – размер сегмента стека в байтах)

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

Очистка и восстановление стека

Иногда приходится очищать стек, т. е. удалять из него несколько последних элементов, никуда их не переписывая. Конечно, здесь можно выполнить нужное число раз команду POP, но это долго. Очистку стека можно сделать и проще, если заметить, что после удаления из стека N слов значение SP должно увеличиться на число 2*N, и если вспомнить, что регистр SP, хотя и специализирован для работы со стеком, все-таки является регистром общего назначения, который можно использовать в любых командах, в том числе и в арифметических. Поэтому очистка стека от N слов осуществляется просто увеличением значения регистра SP на величину 2*N:

ADD SP,2*N ;очистка стека от N слов

Другой вариант очистки стека: запомнить вначале то значение указателя стека SP, до которого затем надо будет очищать стек, после чего можно записывать в стек что угодно, а в конце надо просто восстановить в SP это значение:

MOV AX,SP

... ;запись в стек

MOV SP,AX

Доступ к элементам стека. Регистр ВР

Команды PUSH и POP дают доступ только к вершине стека, но иногда необходим доступ к другим, более «низким» элементам стека. Пусть, к примеру, в стеке записано не менее трех слов и необходимо заслать в регистр АХ копию третьего сверху элемента стека (AX:=w3) (рис. 35).

Рис. 35. Доступ к элементам стека

Как видно, адрес третьего слова стека равен адресу вершины стека плюс 4. Учитывая это, можно сделать следующее: установить регистр ВР на вершину стека и использовать выражение [ВР+4] для доступа к третьему слову:

MOV BP,SP

MOV АХ,[ВР+4] ; = MOV AX,SS:[BP+4]

Почему использован именно регистр ВР? Во-первых, следует отметить, что использовать здесь регистр SP, т. е. выражение [SP+4], нельзя, т. к. SP не относится к числу регистров-модификаторов. Во-вторых, в последней из наших команд неуказан никакой сегментный регистр, поэтому он выбирается по умолчанию. Следует напомнить, что если в команде адрес модифицируется и среди модификаторов есть регистр ВР, то по умолчанию выбирается регистр SS, поэтому наша команда воспринимается как MOV AX,SS:[BP+4], а это значит, что считывание происходит из ячейки сегмента стека. А вот если бы вместо ВР использовался другой модификатор, скажем ВХ, тогда по умолчанию брался бы префикс DS:, что не подходит, и потому пришлось бы явно указывать нужный префикс: MOV AX,SS:[BX+4]. Ясно, что этот вариант хуже, чем вариант с регистром ВР.

Итак, если требуется работать с «внутренними» элементами стека, то надо установить регистр ВР на одну из ячеек стека, например на вершину стека, а затем для ссылок на элементы стека использовать конструкции вида [ВР+n] с подходящим числом n. Поскольку доступ к внутренним элементам стека приходится делать довольно часто, то в ПК и выделили особо регистр ВР, сделали так, чтобы по умолчанию он сегментировался по регистру SS.