Assembler для начинающих


Оператор Assume



Оператор 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      мы  будем использовать  далее в
    примерах.




Содержание раздела