|
| ||
|
|
||
|
| ||
Стек
Стеком называют
область программы
для временного
хранения произвольных
данных. Разумеется,
данные можно
сохранять и в
сегменте данных,
однако в этом
случае для каждого
сохраняемого
на время данного
надо заводить
отдельную именованную
ячейку памяти,
что увеличивает
размер программы
и количество
используемых
имен. Удобство
стека заключается
в том, что его область
используется
многократно,
причем сохранение
в стеке данных
и выборка их оттуда
выполняется
с помощью эффективных
команд push и pop без
указания каких-либо
имен.
Стек традиционно
используется,
например, для
сохранения содержимого
регистров, используемых
программой, перед
вызовом подпрограммы,
которая, в свою
очередь, будет
использовать
регистры процессора
"в своих личных
целях". Исходное
содержимое регистров
извлекается
из стека после
возврата из подпрограммы.
Другой распространенный
прием - передача
подпрограмме
требуемых ею
параметров через
стек. Подпрограмма,
зная, в каком порядке
помещены в стек
параметры, может
забрать их оттуда
и использовать
при своем выполнении.
Отличительной
особенностью
стека является
своеобразный
порядок выборки
содержащихся
в нем данных: в
любой момент
времени в стеке
доступен только
верхний элемент,
т.е. элемент, загруженный
в стек последним.
Выгрузка из стека
верхнего элемента
делает доступным
следующий элемент.
Элементы стека
располагаются
в области памяти,
отведенной под
стек, начиная
со дна стека (т.е.
с его максимального
адреса) по последовательно
уменьшающимся
адресам. Адрес
верхнего, доступного
элемента хранится
в регистре-указателе
стека SP. Как и любая
другая область
памяти программы,
стек должен входить
в какой-то сегмент
или образовывать
отдельный сегмент.
В любом случае
сегментный адрес
этого сегмента
помещается в
сегментный регистр
стека SS. Таким образом,
пара регистров
SS:SP описывают адрес
доступной ячейки
стека: в SS хранится
сегментный адрес
стека, а в SP - смещение
последнего сохраненного
в стеке данного
(рис. 1.10, а). Обратите
внимание на то,
что в исходном
состоянии указатель
стека SP указывает
на ячейку, лежащую
под дном стека
и не входящую
в него.

Рис. 1.10. Организация стека:
а - исходное состояние,
б - после загрузки
одного элемента
(в данном примере
- содержимого
регистра АХ),
в - после загрузки
второго элемента
(содержимого
регистра DS), г
- после выгрузки
одного элемента,
д - после выгрузки
двух элементов
и возврата в исходное
состояние.
Загрузка в стек осуществляется специальной командой работы со стеком push (протолкнуть). Эта команда сначала уменьшает на 2 содержимое указателя стека, а затем помещает операнд по адресу в SP. Если, например, мы хотим временно сохранить в стеке содержимое регистра АХ, следует выполнить команду
push АХ
Стек
переходит в состояние,
показанное на
рис. 1.10, б. Видно, что
указатель стека
смещается на
два байта вверх
(в сторону меньших
адресов) и по этому
адресу записывается
указанный в команде
проталкивания
операнд. Следующая
команда загрузки
в стек, например,
push DS
переведет
стек в состояние,
показанное на
рис. 1.10, в. В стеке
будут теперь
храниться два
элемента, причем
доступным будет
только верхний,
на который указывает
указатель стека
SP. Если спустя какое-то
время нам понадобилось
восстановить
исходное содержимое
сохраненных
в стеке регистров,
мы должны выполнить
команды выгрузки
из стека pop (вытолкнуть):
pop DS
pop AX
Состояние
стека после выполнения
первой команды
показано на рис.
1.10, г, а после второй
- на рис. 1.10, д. Для правильного
восстановления
содержимого
регистров выгрузка
из стека должна
выполняться
в порядке, строго
противоположном
загрузке - сначала
выгружается
элемент, загруженный
последним, затем
предыдущий элемент
и т.д.
Совсем не
обязательно
при восстановлении
данных помещать
их туда, где они
были перед сохранением.
Например, можно
поместить в стек
содержимое DS, а
извлечь его оттуда
в другой сегментный
регистр - ES;
push DS
pop ES ; Теперь ES=DS, а стек пуст
Это
распространенный
прием для перенесения
содержимого
одного регистра
в другой, особенно,
если второй регистр
- сегментный.
Обратите внимание
(см. рис 1.10) на то, что
после выгрузки
сохраненных
в стеке данных
они физически
не стерлись, а
остались в области
стека на своих
местах. Правда,
при "стандартной"
работе со стеком
они оказываются
недоступными.
Действительно,
поскольку указатель
стека SP указывает
под дно стека,
стек считается
пустым; очередная
команда push поместит
новое данное
на место сохраненного
ранее содержимого
АХ, затерев его.
Однако пока стек
физически не
затерт, сохраненными
и уже выбранными
из него данными
можно пользоваться,
если помнить,
в каком порядке
они расположены
в стеке. Этот прием
часто используется
при работе с подпрограммами.
Какого размера
должен быть стек?
Это зависит от
того, насколько
интенсивно он
используется
в программе. Если,
например, планируется
хранить в стеке
массив объемом
10 000 байт, то стек
должен быть не
меньше этого
размера. При этом
надо иметь в виду,
что в ряде случаев
стек автоматически
используется
системой, в частности,
при выполнении
команды прерывания
int 21h. По этой команде
сначала процессор
помещает в стек
адрес возврата,
а затем DOS отправляет
туда же содержимое
регистров и другую
информацию, относящуюся
к прерванной
программе. Поэтому,
даже если программа
совсем не использует
стек, он все же
должен присутствовать
в программе и
иметь размер
не менее нескольких
десятков слов.
В нашем первом
примере мы отвели
под стек 128 слов,
что безусловно
достаточно.
| Физика лабы | ||||||||
| ||||||||