Ассемблирование по условию



Ассемблирование по условию


    До сих пор макрокоманды не отличались от подпрограмм с точки зрения
    как их функционирования, так и использования параметров. Далее, нам
    требуется возмоность ассемблирования в зависимости от условия. Так
    же как ход выполнения подпрограммы может меняться в зависимости от
    некоторых условицй в момент выполнения, так и у макрокоманды должна
    быть возможность изменять в момент транслирования генерацию
    соответствующего машинного кода в зависимости от удовлетворения
    условий.
 
      Макроассемблер фирмы IBM допускает условное ассемблирование. На
    самом деле, условное ассемблирование не обязательно входит только в
    макрокоманду. Программа может использовать условное транслирование
    в любом месте ассемблерного текста. Однако наиболее часто оно
    встречается в макрокомандах. В IBM PC условное транслирование
    поддерживается только Макроассемблером MASM.
 
      Так же, как и выполнение макрокоманд, условное ассемблирование
    происходит во время трансляции, а не выполнения программы. Условное
    транслирование позволяет программисту "запрограммировать" ассемблер
    на транслирование различных последовательостей кодов. Ассемблер
    определяет, что ему транслировать по параметру, известному во время
    ассемблирования. Хотя эта возможность может использоваться
    программой в любой момент ассемблирования, мы изучим прежде всего,
    как она влияет на ассемблирование макрокоманд.
 
      Фиг. 6.4 иллюстрирует условное транслирование при расширении
    макрокоманды FIDIVR сопроцессора 8087. Условное тарнслирование
    требуетя данной макрокоманде из-за разделения переменных в
    ассемблере по типам. Как мы увидим в гл.7, команда, обозначенная
    FIDIVR, может применяться к операндам двух типов. Операнд может
    быть двух- или четырехбайтовым целым числом. Мы хотим, чтобы
    ассемблер выбрал правильный машинный код в зависимости от типа
    операнда. Как мы вмдели, у команды ADD в действительности имеется
    несколько форм, в зависимости от того, какие операнды представлены
    ассемблеру, который выбирает верную форму машинной команды в
    зависиммости от этих операндов. Мы хотим делать то же самое для
    команды FIDIVR Но в теперь макропроцессор должен определить тип
    операнда и сгенерировать правильную команду.
 
      У команды FIDIVR может быть один из двух типов операндов, и в
    зависимости от этого будут различаться результирующие команды.
    Таким образом, расширение макрокоманды FIDIVR должно
    соответствовать нужному операнду. Это обеспечивается двумя
    средствами языка: условным транслированием и оператором TYPE.
      В языке ассемблера имеется оператор TYPE, который возвращает

          Microsoft (R) Macro Assembler Version 5.00              4/2/89 16:06:42
          Фиг. 6.4 Условное транслирование                        Page  1-1
 
                                        PAGE    ,132
                                        TITLE   Фиг. 6.4 Условное транслирование
 
                                  FIDIVR  MACRO   SOURCE
                                        IFE     2 - TYPE SOURCE
                                              DB          09BH        ;; FWAIT
                                              ESC     037H,SOURCE     ;; FIDIVR слово
                                        ENDIF
                                        IFE     4 - TYPE SOURCE
                                              DB          09BH        ;; FWAIT
                                              ESC     017H,SOURCE     ;; FIDIVR короткое целое
                                        ENDIF
                                        ENDM
 
           0000                   CODE    SEGMENT
                                        ASSUME  CS:CODE,DS:CODE
 
           0000  ????             TWO_BYTE          DW          ?
           0002  ????????               FOUR_BYTE         DD          ?
           0006  ??                     ONE_BYTE          DB          ?
 
                                        FIDIVR  TWO_BYTE
           0007  9B                 1              DB          09BH        ;
           0008  DE 3E 0000 R        1              ESC     037H,TWO_BYTE   ;
                                        FIDIVR  FOUR_BYTE
           000C  9B                 1              DB          09BH        ;
           000D  DA 3E 0002 R        1              ESC     017H,FOUR_BYTE  ;
                                        FIDIVR  ONE_BYTE
 
           0011                   CODE    ENDS
                                        END
 
            Фиг. 6.4. Ассемблирование макрокоманд по условию
    значение, равное длине операнда. В случае FIDIVR мы ожидаем, что
    операнд будет двух- или четырехбайтовым целым числом.
 
      Выражение
 
      IFE 2-TYPE SOURCE
 
    в  макрокоманде FIDIVR проверяет длину операнда SOURCE.
    Арифметическое выражение 2=TYPE SOURCE, равняется 0, если операнд
    SOURCE является двухбайтовым целым числом, и принимает ненулевое
    значение при любом другом типе операнда. Оператор IFE
    (транслировать, если равно) сообщает ассемблеру, что нужно
    транслировать все последующие команды, если выражение в поле
    операнда равно 0. Таким образом, оператор IFE вырабатывает значение
    истина, если операнд SOURCE является двухбайтовым целым числом. В
    этом случае происходит трансляция всех команд, следующих за
    оператором IFE до тех пор, пока не встретится оператор ENDIF. В
    нашем примере это означает, что если операнд является двухбайтовым
    целым числом, то ассемблируется участок программы
 
      DB 09BH
      ESC 37H,SOURCE
 
 
      В первом вызове макрокоманды на Фиг. 6.4 в качестве операнда
    используется двухбайтовое целое число. Поэтому, для расширения этой
    макрокоманды ассемблер выбирает команду ESC 37H.
 
      Так как команда FIDIVR имеет два варианта, соответствующие двум
    разным типам операндов, то в при выполнении другого условия,
    макрокоманда использует второй оператор IFE. Когда операнд является
    четырехбайтовым целым числом, макрокоманда генерирует код ESC 17H.
    На Фиг. 6.4 показаны два разных расширения одной макрокоманды.
 
      Обратите внимание, что в последнем из показанных на Фиг. 6.4
    вызовов макрокоманды операнд не удовлетворяет ни одному из условий.
    Так как ни один из операторов IFE не вырабатывает значения
    "истина", то и ассемблироваться не будет ни один из них. В этом
    случае макропроцессор не генерирует никакого кода.
 
      С помощью оператора IFE ассемблер может проверять выполнение
    различных условий. Эти условия приведены в таблице на Фиг. 6.5.
    Общая форма оператора IF имеет вид:
 
      IFхх   выражение
      ...
      ELSE
      ...
      ENDIF
 
      Если значение условия "истина", то ассемблер обрабатывает
    участок программы, следующий за оператором IFхх. Этот транслируемый
    участок программы заканчивается либо оператором ELSE или ENDIF.
    Оператор ELSE не является обязательным. Если он имеется, то
    следующий за ним участок программы будет транслирован при
    невыполнении условия в операторе IF. Оператор ENDIF завершает
    условное ассемблирование и является обязательным.
 
            IF-операция       Ассемблировать если:
      ---------------------------------------------------------------
       IF   выражение   Выражение не равно 0
       IFE  выражение   Выражение равно 0
       IFDEF      имя         Имя уже было описано как внешнее
       IFNDEF имя       Имя еще не описывалось
       IFB  <аргумент>  Аргумент пуст
       IFNB <аргумент>  Аргумент не пуст
       IFIDN      <арг1>,<арг2>     Строка арг1 идентична строке арг2
       IFDIF      <арг1>,<арг2>     Строка арг1 отличается от строки арг2
       IF1              Первый поход ассемблера
       IF2              Второй проход ассемблера
       ---------------------------------------------------------------
            Фиг. 6.5 Операторы IF для условного ассемблирования
 
      Рассмотрим  еще один  пример, чтобы  познакомиться с некоторыми
    другими  вариантами  использования    ассемблирования по условию. На
    Фиг. 6.6  показано применение  другого условного оператора    - IFB, а
    также  использование вложенных  условных операторов.  Макрокомандой
    здесь  является  FLD  -  команда  загрузки  сопроцессора  8087. Для
    транслирования   этой   команды    требуется   несколько   условных
    операторов, так как она может применяться в следующих вариантах:
 
      FLD
      FLD 1
      FLD короткое_вещественное
      FLD длинное_вещественное
      FLD временное_вещественное
 
      Поле операнда макрокоманды FLD может быть пустым, содержать
    константу, или четырехбайтовую, восьмибайтовую либо десятибайтовую
    переменную. Макрокоманда должна распознать каждый из перечисленныз
    случаев и сгенерировать правильный программный код. (все эти типы
    данных рассмотрены очень подробно в гл.7.)
      Оператор IFB проверяет наличие операнда. Если операнд
    отсутствует, то ассемблер генерирует соответствующий этому случаю
    программный код, так как оператор IFB вырабатывает значение
    "истина". Это иллюстрирует первый вызов макрокоманды, когда
    генерируется код
 
      DB 09BH,0D9H,0C 1H
 
      Оператор EXITM, содержащийся в этой части условного оператора
    IF, реализует выход из макрокоманды. Каждый раз, когда при
    расширении макрокоманды ассемблеру встречается этот оператор,
    расширение заканчивается, как если бы встретился ENDM. В данном
    случае ассемблер пропускает оставшуюся часть макроопределения. При
    таком выходе из макрокоманды в ассемблерном листинге появляется
    предупреждающее сообщение "Open conditionals:1" ("Незавершенные
    условные операторы: 1"). Оно предупреждает вас, что ассемблер не Mincho"'>            Microsoft (R) Macro Assembler Version 5.00              4/2/89 16:06:47
            Фиг. 6.6 Вложенные условные макрокоманды                Page         1-1
 
                                          PAGE    ,132
                                          TITLE   Фиг. 6.6 Вложенные условные макрокоманды
 
                                    FLD     MACRO   SOURCE
                                          IFB     <SOURCE>
                                                DB      09BH,0D9H,0C1H        ;; FLD ST(1)
                                                EXITM
                                          ELSE
                                                IFE     TYPE SOURCE
                                                      DB      09BH,0D9H,0C0H+SOURCE
                                                                        ;; FLD ST(i)
                                                ENDIF
                                                IFE     4 - TYPE SOURCE
                                                      DB      09BH
                                                      ESC     8,SOURCE       ;; FLD короткое плавающее
                                                ENDIF
                                                IFE     8 - TYPE SOURCE
                                                      DB      09BH
                                                      ESC     40,SOURCE      ;; FLD длинное плавающее
                                                ENDIF
                                                IFE     4 - TYPE SOURCE
                                                      DB      09BH
                                                      ESC     01DH,SOURCE    ;; FLD временное плавающее
                                                ENDIF
                                          ENDIF
                                          ENDM
 
             0000                   CODE    SEGMENT
                                          ASSUME  CS:CODE,DS:CODE
 
             0000  ????????               FOUR_BYTE       DD      ?
             0004  ????????????????       EIGHT_BYTE      DQ      ?
             000C  ???????????????????      TEN_BYTE        DT      ?
                 ?
                                          FLD
             0016  9B D9 C1            1              DB      09BH,0D9H,0C1H        ;
                                          FLD     1
             0019  9B D9 C1            1                    DB      09BH,0D9H,0C0H+1
                                          FLD     FOUR_BYTE
             001C  9B            1                    DB      09BH
             001D  D9 06 0000 R        1                    ESC     8,FOUR_BYTE     ;
             0021  9B            1                    DB      09BH
             0022  DB 2E 0000 R        1                    ESC     01DH,FOUR_BYTE  ;
                                          FLD     EIGHT_BYTE
             0026  9B            1                    DB      09BH
             0027  DD 06 0004 R        1                    ESC     40,EIGHT_BYTE   ;
                                          FLD     TEN_BYTE
 
             002B                   CODE    ENDS
                                          END
 
            Фиг. 6.6 Вложенное условное ассемблирование
    встретил оператора ENDIF, закрывающего условный оператор. Это
    происходит в результате раннего входа из макрокоманды. Хотя это и
    нежелательно, но ни к каким разрушительным последствиям не
    приводит. Если оператор EXITM расположен вне условного оператора,
    то предупреждение не выводится.
      Оператор EXITM необходим в данной макрокоманде, так как
    ассемблер проверяет все условные операторы, даже если они не
    транслируются. В нашем случае, если операнд SOURCE пуст, оператор
    ELSE предотвращает генерацию всех других вариантов команды FLD.
    Однако, продолжая просмотр, ассемблер проверяет оператора
 
      IFE TYPE SOURCE
 
      хотя и не может сгенерировать никакого кода. Если SOURCE пусто,
    то ассемблер фиксирует синтаксическую ошибку. Вы можете не обращать
    внимания на эту ошибку, но принимать трансляцию с сообщениями об
    ошибках идет в разрез с нашими правилами. С другой стороны,
    использование оператора EXITM приводит к предупреждению "Открытое
    условие". Оно нежелательно, но это меньшее из двух зол.
 
      Заметим, что макрокоманда FLD использует ветвь ELSE чтобы
    указать на необходимость вычисления выражения в поле операнда
    только в случае непустоты этого поля. IF-выражения, содержащие
    оператор TYPE, определяют, какой тип операнда использовался при
    вызове макрокоманды. Хотя это не упоминается в Руководстве по
    Макроассемблеру, оператор TYPE возвращает значение 0, если операнд
    является не символическим именем, а константой. Выбор такого
    способа в данной макрокоманде вызван скорее соображениями
    работоспособности, чем стремлением к элегантности.




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