|
После тогокак
сегменты впрограмме определены,
ассемблердолжен
узнать,какбудутустановленысегментныерегистрывовремя
выполнения программы. В примере наФиг. 3.9 всего три сегмента, но
болшаяпрограммаможетиметьнамногобольше.Располагая всего
четырьмясегментными регистрами,большая
программаможет адресо-
ваться одновременно только к части
доступных сегмментов. Ассемблеру
необходимо сообщить, к какимименно сегментам происходит адресация
вовремявыполнения.Этоделаетсяспомощьюоператора ASSUME
которыйописывает дляассемблера
установкисегментных регистров.
Программистдолженсвязатькаждыйсегментныйрегистрстем
сегментом, на который тот в данный момент
указывает.
Фиг. 3.9 иллюстрирует такие сегментные
операции. В этом примере
имеется трисегмента: DATA, BUFFERи
CODE. Именадля них выбраны
произвольно. Их выбирает программист, а
для ассемблера они не имеют
значения.Например,выможетеназватьсегментименемCODE,
а
использовать его только для данных и
наооборот. Лучше всего, конеч-
но, называтьсегменты так, чтобыих
имена имеликакой-то смысл в
данной программе. В нашем примересегменты DATA и BUFFER оба имеют
внутриячейку данных.Вряд лиреальная программабудет задавать
сегментлишь содной ячейкойпамяти, носейчас этослужит для
примера.Если программаобращаетсякданным вомногих участках
адресуемого в 8088 пространства,то ей требуется много определений
сегментов. Например, программауправления устройствами доступа IBM
PCможетобращатьсякпамятивсистемнойобластиданных,
устанавливать векторы прерываний вначале памяти и выполняться как
программа влюбом другом месте.Каждая из этихобластей является
сегментом и должна быть определена в
программе.
Утверждение ASSUME на Фиг. 3.9
предписывает ассемблеру работать
с учетом следующейустановки сегментных регистров:регистр CS со-
держит начальный адрес сегмента CODE,
регистр DS указывает на DATA,
а регистрESопределяет
сегментBUFFER.УтверждениеASSUME
(полагать,считать
-прим. перев.)означает именното, чтооно
предписываетассемблеру.Ассемблеробрабатываетисходныйтекст
программыпредполагая,чтосегментныерегистрыустановлены как
указано в этом утверждении. Установка
сегментных регистров, сделан-
ная вэтом утверждении, остаетсяпри
ассемблировании всиле пока
другое такое же утверждение не определит
новые установки. Ассемблер
обрабатывает этиутверждения последовательно, дажеесли программа
ветвитсяи закручиваетсяв циклы.Утверждение ASSUMEостается в
силе,пока ассемблерне встретитпри последовательномпросмотре
программы следующее.Заметим, что в утвержденииASSUME не обязано
определятьвсе
сегментныерегистры. Внашем примерене объявлен
регистр SS.На практике содержимое сегментногоргистра может быть
временамии неизвестновпрограмме.В этихслучаях
утверждение
ASSUME должно указывать сегмент NOTHING.
Например, утверждение
ASSUMEES:NOTHING
сообщает ассемблеру, что программане знает, куда указывает допол-
нительный сегментный регистр. Поскольку
значение регистра неизвест-
но, ассемблер не должен использовать его в
адресных вычислениях.
Важно отметить, что утверждение ASSUME не
генерирует команд ма-
шинногоязыка. Этодиректива
ассемблеруполагать, что сегментные
регистры установлены в соответствиис указанной в этом утверждении
информацией.Добитьсяправильноеустановкисегментов-забота
программиста. Аналогично, ассемблер не
может проверить, что утверж-
дениеASSUMEпривыполнениибудетсоответствоватьсодержимому
сегментныхрегистров.
Из-затого,чтопрограмма можетприйти к
любомуконкретномуASSUMEмножествомразныхпутей,заего
корректность отвечает программист.В нашем примере предполагается,
что сегментные регистры
устанавливаютсядо выполнения данного
кус-
ка программы. Если они установленыы
неверно, то программа будет вы-
полняться неправильно даже если
ассемблирование прошло успешно.
Первая команда увеличивает значение VAR1,
находящейся в сегмен-
те данных. Ассемблер полагает, что регистр
DS указывает на сегмент
DATAв соответствиис
утверждениемASSUME. Посколькурегистр DS
предполагается прииспользовании данных по умолчанию,то для этой
команды ассемблер негенерирует сегментный префикс.
Сформированная
этой инструкцией 4-байтовая машинная
команда не содержит сегментно-
гопрефикса.
Вторая команда определяет переменнуюVAR2, которая находится в
сегментеназванномBUFFER.Программасообщилаассемблеру,что
дополнительный сегментный регистр
указываетна сегмент BUFFER. Для
увеличения VAR2 ассемблер генерирует
четырехбайтовую команду машин-
ного языка,но ей предшествуеткоманда с однобайтовымпрефиксом,
котораяотменяетиспользованиерегистраDSвэтойкоманде.
Префиксныйбайт
26Hговорит процессоруиспользовать при создании
20-битового адреса памяти регистр ES.В колонке объектных кодов на
листинге ассемблер отмечает префиксную
команду двоеточием.
ТретьякомандаизменяетпеременнуюVAR3всегментеCODE.
Утверждение ASSUME связывает этот сегмент
с регистром CS. Ассемблер
автоматическигенерируетсоответствующийпрефикспереназначения
сегмента.Вданномслучаепрефикс2EHпредписывает процессору
использоватьпривычислениииспольнительногоадреса регистр CS.
ВначалеутверждениеASSUMEпокажетсяизлишеством.В первое
время принаписании программы естественно забыватьо его примене-
нии. Ассемблер выдаст массу сообщений об
ошибках чтобы помочь вам в
вашейзабывчивости. Нопри
достаточномопыте, утверждение ASSUME
помогает программисту ассемблера
сосредоточиться на структурах дан-
ныхвпрограмме.Программистдолженнезабывать устанавливать
сегментные регистрыдля адресации требуемыхдля программы данных.
Ассемблероблегчитбремязапоминаниядлякаждойкоманды,где
располагаютсяданныеикакойсегментныйрегистрдолженбыть
использован чтобы попасть к ним.
Программа можетиспользовать утверждение SEGMENTдля передачи
информациидругимпрограммам.ОператорSEGMENTможетзадавать
выравнивание сегмента в памяти,способ его комбинирования с други-
мисегментами
иимя еготипа. Дляпрограммистов
IBMPC особый
интерес представляют двавида выравнивания сегментов. Выравнивание
попараграфам(типPARA)размещаетначалосегментасначала
параграфа -ячейки памяти, адрескоторой в памятикратен 16-ти .
Этоозначает,чтопервыйбайтсегментабудет иметь смещение 0
относительно значения сегментногорегистра. Выравнивание по байтам
(типBYTE), наоборот,размещает
сегментв любомместе памяти. В
этом случае сегментный регистр можети не указывать на первый байт
сегмента.В программеможет
потребоватьсяненулевое смещение для
доступа к началу сегмента.
Различныеспособысвязываниясегментовзадаетпараметр типа
связи.Особенноэтополезнопримодульномпрограммировании.
Описание PUBLIC приводит к объединению
всех сегментов с одинаковыми
именамив одинбольшойсегмент.Например,
можнообъединить все
сегменты кодов.Это приведет к соединениюразных
подпрограмм в их
собственных модулях с главной процедурой.
Другой полезный тип связи
- AT,при указаниикотороговсочетании садресным выражением,
сегментрасполагаетсяпо заданномуабсолютномуадресу.Такое
объявление необходимопри работе с даннымив фиксированном месте,
например, с векторами прерываний в начале
памяти.
Намногоболееполноеописаниеописаниеутверждения SEGMENT
можно найтив справочном томе кмакроассемблеру IBM PC. Некоторые
извозможностей
опертораSEGMENTмыбудем использоватьдалее в
примерах.
|