Оператор Assume

    После того    как сегменты в    программе определены, ассемблер  должен

    узнать,  как   будут  установлены  сегментные   регистры  во  время

    выполнения программы. В примере на    Фиг. 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. Например, утверждение

 

      ASSUME      ES: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      может  задавать

    выравнивание сегмента в памяти,  способ его комбинирования с други-

    ми      сегментами и  имя его   типа. Для  программистов IBM  PC особый

    интерес представляют два  вида выравнивания сегментов. Выравнивание

    по      параграфам  (тип  PARA)  размещает  начало  сегмента  с  начала

    параграфа -  ячейки памяти, адрес  которой в памяти  кратен 16-ти .

    Это  означает,  что  первый  байт  сегмента  будет иметь смещение 0

    относительно значения сегментного  регистра. Выравнивание по байтам

    (тип  BYTE), наоборот,  размещает сегмент  в любом      месте памяти. В

    этом случае сегментный регистр может  и не указывать на первый байт

    сегмента.  В программе  может потребоваться  ненулевое смещение для

    доступа к началу сегмента.

       Различные  способы  связывания  сегментов  задает  параметр типа

    связи.  Особенно   это  полезно  при   модульном  программировании.

    Описание PUBLIC приводит к объединению всех сегментов с одинаковыми

    именами  в один  большой  сегмент.    Например, можно  объединить все

    сегменты кодов.  Это приведет к соединению  разных подпрограмм в их

    собственных модулях с главной процедурой. Другой полезный тип связи

    - AT,  при указании  которого  в  сочетании с  адресным выражением,

    сегмент  располагается  по      заданному  абсолютному  адресу.  Такое

    объявление необходимо  при работе с данными  в фиксированном месте,

    например, с векторами прерываний в начале памяти.

      Намного  более    полное      описание  описание  утверждения SEGMENT

    можно найти  в справочном томе к  макроассемблеру IBM PC. Некоторые

    из      возможностей опертора  SEGMENT      мы  будем использовать  далее в

    примерах.