Сегментные регистры
Суть сегментной адресации ячеек памяти “восходит” к модели МП 8086 и заключается в следующем. В реальном режиме МП доступен 1М памяти, для адресации которого необходимы 20-разрядные регистры. Фактическая разрядность регистров МП 8086 – 16 разрядов, что позволяло адресовать участок памяти только в 64К, получивший название сегмент.
Полный 20-разрядный адрес формируется из двух 16-разрядных значений seg:off, гдеseg– адрес сегмента (базовый адрес), аoff– смещение в нем, по следующей формуле:
16Segoff
Например, логический адрес 1234:0001 преобразуется в полный физический
-
12340
увеличенный на 16 seg
0001
16-битноеoff
12341
20-битный физ. адрес
Пример использования сегментного регистра CSдля адресации двух сегментов кодов:Code1 иCode2.
ASSUME CS:Code1
Code1 SEGMENT
Star: ;здесь CS=SEG Code1, IP=OFFSET Start
jmp far ptr Lab ;дальняя передача управления в Lab
Code1 ENDS
ASSUME CS:Code2
Code2 SEGMENT
Lab ;здесь CS=SEG Code2, IP=OFFSET Lab
mov ax,4c00h ;код возврата 0
int 21h
Code2 ENDS
Stack_ SEGMENT STACK
DB 100h DUP(?)
Stack_ ENDS
END Start
2.2 Организация и работа стека
Стек – это область памяти с LIFO-алгоритмом доступа к ячейкам, т.е. доступной для операций ЧТ/ЗП является верхняя ячейка.
Рис.
2.
Элементы стека располагаются в области памяти, отведенной под стек, начиная со дна стека (т.е. с его максимального адреса) по последовательно уменьшающимся адресам. Адрес верхнего, доступного элемента хранится в регистре-указателе стека SP. Как и любая другая область памяти программы, стек должен входить в какой-то сегмент или образовывать отдельный сегмент. В любом случае сегментный адрес этого сегмента помещается в сегментный регистр стека SS. Таким образом, пара регистров SS:SP описывает адрес доступной ячейки стека
Примечательно, что в исходном состоянии указатель стека SP указывает на ячейку, лежащую под дном стека и не входящую в стек (рис. 2а).
Загрузка данных в верхнюю ячейку стека (запись) осуществляется командой PUSH, а извлечение данных из верхней ячейки стека (чтение) –POP. Формат данных – 16 бит. Синтаксис командPUSH,POP:
PUSHор =
POPор =
,
где ор – операнд.
На рис. 2б-2в показано перемещение SPпри загрузке стека; 2г-2д демонстрируют перемещениеSPпри извлечении данных из стека, причем после командыPOPстек физически не затерт. Следовательно, принудительно изменив значениеSP, можно обратиться к произвольной ячейке стека. Этот прием часто используется при работе с подпрограммами.
В случае отсутствия явного объявления сегмента стека в программе, операционная система сама создает стек по умолчанию в сегменте кода. Служебная (а не пользовательская!) необходимость в стеке возникает при выполнении команд CALL,INT. Корректное завершение этих команд связано с восстановлением состояния МП при возвращении в основную программу из подпрограммы или прерывания. В общем случае, состояние МП – это:
адрес следующей после CALLINT команды (адрес возврата);
состояние регистра флагов
. состояние универсальных регистров
Рассмотрим пример программы без объявления сегмента стека:
Text segment ‘code’ ;(1) Начало сегмента команд
assume CS:text,DS:data;(2) CSсегмент команд
; DSсегмент данных
begin mov AX,data ;(3) Адрес сегмента данных загрузим
mov DS,AX ;(4) Сначала в АХ, затем в DS
push DS ;(5) Загрузим в стек содержимое DS
pop ES ;(6) Выгрузим его из стека ES
mov AH,9 ;(7)Функция DOS вывода на экран
mov DX,offset message;(8) Адрес выводимого сообщения
int 21h ;(9) Вызов DOS
mov AX,4C00h ;(10) Функция завершения программы
; с указанием кода завершения 00h
int 21h ;(11) Вызов DOS
text ends ;(12) Конец сегмента данных
data segment ;(13) Начало сегмента данных
message db ‘Наука умеет много гитик$’;(14) Выводимый текст
data ends ;(15) Конец сегмента данных
ends begin ;(16) указание точки входа в программу
После инициализации программы (рис.3) DSуказывает на отдельный сегмент данных, аSS=CS. Следовательно,CS:0000 – адрес дна стека. Поскольку значениеSPинтерпретируется как беззнаковое, то первая операция загрузки в стек приведет к обращению к верхушке стека в конец сегмента кода по адресуCS:FFFEh. В дальнейшем заполнение стека будет вестись снизу-вверх в сегменте кода, проходя значенияCS:FFFCh,CS:FFFAh,CS:FFF8 и т.д

