Здавалка
Главная | Обратная связь

Размещение сегментов программы



Ранее уже говорилось, что в ЭВМ, сконструированных на базе мик- ропроцессоров 8086 и 8088, программы и данные хранятся в отдельных областях памяти. Эти области (или сегменты) могут иметь объем до 64 Кбайт. Микропроцес- сор 8088 может иметь дело одновременно с четырьмя сегментами. Начальные адреса этих сегментов содержатся в его четырех регистрах сегментов. Эти регистры выполняют следующие функции: регистр сегмента команд CS (code segment) указывает на сегмент, содержащий текущую исполняемую программу.

Для вычисления адреса следующей исполня- емой команды микропроцессор 8088 добавляет к содержимому регистра CS (умноженному на 16) содержимое указателя команд IP; регистр сегмента стека SS (stack segment) указывает на текущий сегмент стека. Стек представляет собой область памяти, используемую для временного хра- нения данных и адресов. Микропроцессор 8088 использует стек для хранения адреса возврата из текущей подпрограммы, но стек можно использовать также для восстановления содержимого регистров, изменяемых при работе програм- мы. Позже мы рассмотрим стеки более подробно; регистр сегмента данных DS (data segment) указывает на текущий сегмент дан- ных, обычно содержащий используемые в программе переменные; регистр дополнительного сегмента ES (extra segment) указывает на текущий дополнительный сегмент, который используется при выполнении операций над строками.

Регистры указателей и индексов

Вспомните, что для вычисления адреса команды в сегменте команд микропроцессор 8088 извлекает номер блока памяти из регистра CS, а смеще- ние- из регистра IP. Подобным образом за счет выбора номера блока из соответ- ствующего регистра сегмента, а смещения - из другого регистра осуществляется доступ к данным других сегментов. Для доступа к сегменту данных микропроцес- сор 8088 извлекает номер блока из регистра DS, а смещение - из регистра ВХ или индексного регистра (SI или DI). Для доступа к сегменту стека микропроцессор 8088 извлекает номер блока из регистра SS, а смещение - из регистра указателя (SP или BP). Выбирая номер блока из регистра ES, микропроцессор может также полу- чить доступ к дополнительному сегменту

Стековые операции

В гл.3 обсуждалось, как реализован стек в микропроцессоре 8088. Микропроцессор 8088 адресует стек с помощью регистровой пары SS:SP. Помещение объектов в стек приводит к тому, что он растет в сторону меньших адресов памяти. Стек, кроме всего прочего, служит и для запоминания адресов возврата из подпрограмм. В этом разделе рассматриваются некоторые команды, которые непосредственно работают со стеком.

Мнемоника команд очевидна; за кодами операций PUSH и POP следует имя регистра для указания операнда. Единственным исключением является помещение и извлечение из стека регистра флагов, которые используют мнемонику PUSHF и POPF соответственно. Содержимое любой ячейки памяти, которую программа может адресовать, используя возможные способы адресации, также может быть помещено или извлечено из стека.

При любых действиях со стеком в микропроцессоре 8088 базовой единицей информации является 16-битовое слово. Длина любого объекта, помещаемого в стек либо извлекаемого из стека, составляет одно или несколько слов. Байтовых команд, связанных с засылкой данных или извлечением их из стека, не существует. Если, например, программе необходимо сохранить содержимое регистра AL в стеке, она должна поместить содержимое регистра AX, так как не существует способа сохранения только содержимого регистра AL.

Основное назначение стека - временное хранение информации. Как мы уже видели, стек используется для сохранения адреса возврата; программа также может сохранять данные. Если программа хочет использовать регистр, пусть даже сохранить текущие данные, она может послать значение этого регистра в стек. Эти данные сохраняются в стеке и позже могут быть восстановлены. Например, программе нужно ввести код из порта ввода-вывода 3DAH, а в регистре DX находятся важные данные. Следующая последовательность команд

PUSH DX

MOV DX,3DAH

IN AL

POP DX

сохраняет регистр DX в стеке на то время, пока он нужен в программе для выполнения команды IN.

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

Помните о том, что стек - это структура типа LIFO. Если в вашей программе выполняется последовательность команд

PUSH BX

PUSH CX

POP BX

POP CX

то результирующим эффектом будет обмен значений в регистрах BX и CX. Только тот факт, что в команде PUSH был указан регистр BX, не означает, что команда POP, указывающая на тот же регистр, восстанавливает первоначальное содержимое регистра BX. Еще одним важным моментом является то, что команды PUSH и POP должны быть сбалансированы, т.е. каждой команде PUSH должна соответствовать команда POP. Точно так же, как и в случае скобок в арифметическом выражении, если посылки и извлечения из стека не сбалансированы, результаты будут неверны. Более того, несбалансированные команды PUSH/POP обычно приводят к возврату из подпрограмм по адресу значения данных, а не значения указателя команд из-за того, что микропроцессор 8088 записывает в стек адрес возврата. Обычно это вынуждает микропроцессор выполнять программу, которую программист никогда не писал. Поэтому баланс стековых команд обязателен. Будьте особенно внимательны в тех случаях, когда в программе есть условный переход вокруг стековых операций; можно легко выпустить из виду один из вариантов выполнения, что оставит стек несбалансированным.

Наряду с сохранением данных, программа может использовать стек в качестве буфера при некоторых пересылках; в частности, не существует команды пересылки, которая бы переносила данные из одного сегментного регистра в другой. В обычном случае загрузка одного сегментного регистра из другого требует сначала загрузки его значения а промежуточный регистр. Это достигается следующей последовательностью из двух команд:

MOV AX,CS ; переслать значение регистра CS в регистр AX

MOV DS,AX; загрузить это значение в регистр DS

Каждая из этих команд имеет длину несколько байт, и эта последовательность разрушает содержимое регистра AX.

Альтернативным подходом может быть

PUSH CS ; регистр CS поместить в стек

POP DS; поместить это значение в регистр DS

Результирующий эффект этой последовательности команд тот же, регистр DS загружается из регистра CS. Здесь длина программы - всего два байта, и к тому же не требуется промежуточный регистр. Однако эти две команды занимают больше времени, так как нужны дополнительные циклы чтения и записи в стек. Это - метод потери в скорости выполнения ради уменьшения размера объектного кода.

 







©2015 arhivinfo.ru Все права принадлежат авторам размещенных материалов.