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

    До сих пор макрокоманды не отличались от подпрограмм с точки зрения

    как их функционирования, так и использования параметров. Далее, нам

    требуется возмоность ассемблирования в зависимости от условия. Так

    же как ход выполнения подпрограммы может меняться в зависимости от

    некоторых условицй в момент выполнения, так и у макрокоманды должна

    быть возможность изменять в момент транслирования генерацию

    соответствующего машинного кода в зависимости от удовлетворения

    условий.

 

      Макроассемблер фирмы 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, если операнд

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

    способа в данной макрокоманде вызван скорее соображениями

    работоспособности, чем стремлением к элегантности.

Hosted by uCoz