ЭЛЕКТРОННАЯ БИБЛИОТЕКА КОАПП
Сборники Художественной, Технической, Справочной, Английской, Нормативной, Исторической, и др. литературы.



5. Макросредства
               Макросредства языка ассемблера позволяют формировать в 
         исходной  программе  блоки  предложений  (макроопределения), 
         имеющие одно общее имя, и затем многократно использовать это 
         имя   для   представления   всего    блока.    В    процессе 
         ассемблирования    MASM    автоматически   замещает   каждое 
         распознаваемое макроимя  (макрокоманду)  последовательностью 
         предложений в соответствии с макроопределением, в результате 
         чего формируется макрорасширение. 
               Макрокоманда  может встречаться в  исходной  программе
         столько  раз,  сколько  это  необходимо.  Макроопределение в
         исходном   файле   должно   предшествовать    его    первому
         использованию  в  макрокоманде.  Макроопределение  может как
         непосредственно  находиться  в  тексте  программы,   так   и
         подключаться из другого файла директивой INCLUDE (п.8.1).
               В  макроопределение  могут  быть  переданы  параметры,
         которые   могут  управлять  макроподстановкой  или  задавать
         фрагменты текста.
               В программе на языке ассемблера макрокоманды выполняют
         в целом те же функции, что и  процедуры,  т.е.  обеспечивают
         многократное   и   функционально   законченное   действие  с
         параметрическим   управлением.   Различие   заключается    в
         следующем:
               1.  Процедура  присутствует  в исходной программе один
         раз, тогда как  тело  макроопределения  дублируется  столько
         раз,  сколько  соответствующих макрокоманд содержит исходный
         файл.
               2. Текст процедуры статичен и неизменен  в  то  время,
         как состав  макрорасширения  может  зависеть  от  параметров
         макрокоманды. Следует помнить, что параметры макрокоманды  -
         это  значения времени ассемблирования, а параметры процедуры
         принимают какие-то определенные  значения  лишь  в  процессе
         выполнения программы.
               
               Основные  макродирективы  описаны в п.5.1.
               В  п.5.2  содержатся  сведения  о  блоках  повторения,
         которые в целом можно считать частным случаем макродиректив,
         хотя они имеют определенную специфику.
               В п.5.3 описаны макрооператоры, позволяющие  выполнять
         некоторые  функции  над  параметрами  макрокоманды и другими
         элементами исходного текста.
               
               
               
               
               
               

                                   - 22 -
         
         
                            5.1. Макродирективы.
               
               
               Макроопределение  представляет  собой  блок   исходных
         предложений, начинающийся директивой MACRO и заканчивающийся
         директивой ENDM. Формат макроопределения:
               
        имя MACRO [[формальный-параметр,...]]
               предложения
            ENDM
               
               Именем макроопределения  считается  имя,  указанное  в
         директиве MACRO. Оно должно быть уникальным и используется в
         исходном  файле  для  вызова  макроопределения.   Формальные
         параметры  представляют  собой  внутренние  по  отношению  к
         данному  макроопределению  имена,  которые используются  для
         обозначения  значений,  передаваемых  в макроопределение при
         его вызове. Может быть  определено  любое  число  формальных
         параметров,  но  все они должны помещаться на одной строке и
         разделяться запятыми (если их несколько).
               В теле макроопределения  допустимы  любые  предложения
         языка  ассемблера,  в  том  числе  и  другие макродирективы.
         Допустимо  любое  число   предложений.   Каждый   формальный
         параметр  может  быть  использован  любое  число  раз в этих
         предложениях.
               Макроопределения  могут  быть  вложенными,  т.е.  одно
         макроопределение   может   содержаться  в  другом.  MASM  не
         обрабатывает вложенные макроопределения до тех пор, пока  не
         будет  вызвано  внешнее  макроопределение. Поэтому вложенное
         макроопределение не может быть вызвано до тех пор, пока хотя
         бы  один  раз  не  было  вызвано  внешнее  макроопределение.
         Глубина вложенности может быть произвольной и ограничивается
         лишь размером доступной при ассемблировании памяти.
               Макроопределения   могут   содержать   вызовы   других
         макроопределений. Такие вложенные макровызовы обрабатываются
         так же, как и  другие  макровызовы,  но  лишь  тогда,  когда
         вызвано внешнее макроопределение.
               Макроопределения   могут   быть   рекурсивными,   т.е.
         вызывать сами себя.
               MASM  ассемблирует  предложения  тела макроопределения
         только при макровызове и только в той точке исходного файла,
         где  этот  вызов  имеет  место.  Таким образом, все адреса в
         ассемблируемом коде будут связаны с точкой макровызова, а не
         местоположением  макроопределения.  Макроопределение само по
         себе никогда не ассемблируется.
               Следует соблюдать осторожность при использовании слова
         MACRO  после  директив  TITLE, SUBTTL и NAME. Т.к. директива
         MACRO  "перекрывает"  эти  директивы,  использование  такого
         слова   после   указанных  директив  приведет  к  тому,  что
         ассемблер начнет создавать макро с именами TITLE, SUBTTL или
         NAME. Например, предложение
               TITLE Macro File
         может  быть  внесено  в исходный файл для создания заголовка
         "Macro File", но в результате будет создано макроопределение
         с   именем  TITLE,  имеющее  формальный  параметр  File,  а,

                                   - 23 -
         
         
         поскольку в этом случае, очевидно,  не  будет  предусмотрена
         директива    ENDM,   закрывающая   макроопределение,   будет
         скорее всего генерироваться сообщение об ошибке.
               Следует помнить, что MASM замещает все вхождения имени
         формального   параметра   в   теле   макроопределения    его
         фактическим  значением, даже если программисту это не нужно.
         Например,   если   формальный   параметр  имеет  имя  AX,  в
         генерируемом макрорасширении MASM замещает все вхождения  AX
         на  значение  фактического  параметра.  Если  же  по  логике
         макроопределения необходимо использование регистра AX, а  не
         одноименного   формального  параметра,  код  макрорасширения
         может быть некорректным.
               Макроопределения  могут  быть переопределены. При этом
         можно не заботиться об удалении из исходного  файла  первого
         макроопределения,  т.к.  каждое  следующее  макроопределение
         автоматически замещает предыдущее макроопределение с тем  же
         именем.   Если  переопределение  совершается  внутри  самого
         макроопределения, необходимо помнить, что между  директивами
         ENDM,  закрывающими  старое  и  новое  макроопределения,  не
         должно  находиться  никаках   строк.   Например,   следующее
         переопределение некорректно:
               
               dostuff MACRO
                  ...
                  dostuf MACRO
                     ...
                  ENDM
                  ;; Ошибочная строка
               ENDM
               
               
               Макроопределение может быть  вызвано  в  любой  момент
         простым  указанием его имени в исходном файле (имена макро в
         комментариях   игнорируются).   MASM   при   этом   копирует
         предложения   макроопределения   в   точку  вызова,  замещая
         в этих  предложениях  формальные  параметры  на  фактические
         параметры, задаваемые при вызове.
               Общий вид макровызова:
               
               имя [[фактический-параметр,...]]
               
               Имя  должно быть именем ранее определенного в исходном
         файле макроопределения. Фактическим  параметром  может  быть
         имя,  число  или  другое  значение.  Допустимо  любое  число
         фактических параметров, но  все  они  должны  помещаться  на
         одной строке. Элементы списка параметров должны  разделяться
         запятыми, пробелами, или TAB-символами.
               MASM  замещает  первый  формальный  параметр на первый
         фактический параметр, второй формальный параметр  на  второй
         фактический параметр и т.д. Если  фактических  параметров  в
         макровызове    больше,    чем    формальных   параметров   в
         макроопределении, лишние фактические параметры игнорируются.
         Если  же  фактических  параметров  меньше,  чем  формальных,
         формальные параметры, для  которых  не  заданы  фактические,
         замещаются пустыми  строками  (пробелами).  Для  определения

                                   - 24 -
         
         
         того,  заданы  или  не  заданы  соответствующие  фактические
         параметры могут быть использованы директивы IFB, IFNB, .ERRB
         и .ERRNB (п.п.4.1 и 4.2).
               В  макросредствах языка ассемблера имеется возможность
         передавать список значений в качестве одного параметра. Этот
         список должен быть заключен в одинарные скобки < и >, а сами
         элементы списка - разделяться запятыми. Пример:
               
               allocb <1,2,3,4>
               
               При  написании   макроопределений   иногда   возникает
         необходимость  в  задании  меток  инструкций  или имен полей
         данных.    Поскольку    каждое    макроопределение     может
         использоваться многократно, может возникнуть ситуация, когда
         несколько имен или меток определены многократно, что вызовет
         ошибку  трансляции.  Для  обеспечения  правильной  обработки
         таких ситуаций в макроязыке предусмотрена  директива  LOCAL,
         позволяющая  локализовать  заданные  имена  исключительно  в
         данном макрорасширении. Формат:
               
               LOCAL формальное-имя,...
               
               Формальное-имя может  затем  использоваться  в  данном
         макроопределении  с уверенностью, что при каждом макровызове
         его значение будет уникальным. В директиве LOCAL,  если  она
         присутствует, должно быть задано хотя бы одно имя, а если их
         несколько, они должны разделяться запятыми.
               Для обеспечения уникальности  определенных  директивой
         LOCAL   имен  MASM  для  каждого  такого  имени  при  каждом
         макровызове порождает реальное имя следующего вида:
               
         ??номер
               
               Номер представляет собой 16-ричное число в пределах от
         0000 до FFFF. Для предотвращения повторного определения имен
         программисту не рекомендуется определять в  своей  программе
         имена этого типа.
               Директива   LOCAL   может   использоваться   только  в
         макроопределении, причем, там она должна предшествовать всем
         другим   предложениям   макроопределения,   т.е.   следовать
         непосредственно после MACRO.
               
               Для удаления макроопределений служит директива  PURGE.
         Формат:
               
               PURGE имя-макроопределения,...
               
               Удаляются  все  текущие  макроопределения с указанными
         именами. Последующий вызов одного из  этих  макроопределений
         будет приводить к ошибке.
               Директива PURGE введена для возможности освобождения и
         повторного использования памяти, занимаемой  неиспользуемыми
         в  дальнейшем  макроопределениями. Если имя-макроопределения
         представляет    мнемонику    инструкции    или    директивы, 
         восстанавливается    первоначальный    смысл   мнемоники   в

                                   - 25 -
         
         
         соответствии со значением данного ключевого слова.
               Директива  PURGE  часто  используется   для   удаления
         ненужных макроопределений из подключаемой директивой INCLUDE
         библиотеки  макроопределений.   Библиотека  макроопределений
         представляет собой  обычный последовательный файл, который в
         общем случае может содержать большое число макроопределений.
         Комбинация директив INCLUDE и PURGE позволяет выбрать из них
         только нужные  для  данной программы,  что  сократит  размер
         исходного файла.
               Нет  необходимости  удалять макроопределения  после их
         переопределения, т.к.  каждое  переопределение автоматически
         удаляет предшествующее  макроопределение  с  данным  именем.
         Аналогично каждое макроопределение может удалить  само себя,
         имея  в  своей  последней  обрабатываемой  строке  директиву
         PURGE.
               
               Конец     текущего    макроопределения    обозначается
         директивой  ENDM,  которая  должна  находиться  в  последней
         строке макроопределения. Формат:
               
               ENDM
               
               Выход  из  текущего  макроопределения   до  достижения
         директивы   ENDM  обеспечивается директивой  EXITM,  имеющей
         следующий формат:
               
               EXITM
               
               Выход из макроопределения по директивам  ENDM  и EXITM
         заключается в прекращении генерации текущего макрорасширения
         и  возврате  в  точку  вызова  текущего  макроопределения  в
         динамически   внешнем   макрорасширении   или   в   исходной
         программе.
               
               Пример:
               
         add   MACRO param
               IFB   param
               EXITM
               ENDIF
               ADD   AX,param
               ENDM
               
               В  этом   мароопределении   осуществляется  добавление
         величины,   определяемой   формальным  параметром  param,  к
         содержимому регистра AX. Блок условного ассемблирования  IFB
         обеспечивает  выход  из  макроопределния,  если  при  вызове
         параметр не был задан.
               
               
               
               
               
               
               

                                   - 26 -
         
         
               
                           5.2. Блоки повторений.
               
               
               
               Блок повторения представляет собой специфическую форму
         макроопределения  с  несколько  ограниченными  возможностями
         макроязыка.   По  сути  блок  повторения  представляет собой
         макрообъект,   объединяющий   в   себе   макроопределение  и
         макровызов.   Макроопределения  как   шаблона,  по  которому
         производится генерация макрорасширения, здесь не  требуется,
         в   результате   чего   сужаются   возможности  варьирования
         генерируемым текстом. С другой стороны, использование блоков 
         повторения   по  сравнению   с  макроопределениями  является
         синтаксически и логически более простой задачей.
               Обработка блока  повторения заключается в многократном
         дублировании  тела  блока  с   незначительными   изменениями
         текста.
               В языке ассемблера имеются блоки повторения 3-х типов:
         REPT-блок, IRP-блок и IRPC-блок.
               
               
               REPT-блок имеет следующий формат:
               
               REPT выражение
                  ...
                предложения
                  ...
               ENDM
               
               Блок предложений, заключенный между  ключевыми словами
         REPT   и  ENDM,  повторяется  столько  раз,  каково  текущее
         значение  указанного  выражения.  Выражение   должно   иметь
         значение  в  виде  16-битового  числа  без  знака и не может
         содержать внешних или неопределенных  символов.  Тело  блока
         может включать в себя любые предложения языка.
               
               
               IRP-блок имеет следующий формат:
               
               IPR формальный-параметр,<параметр,...>
                  ...
                предложения
                  ...
               ENDM
               
               Блок  предложений, стоящий между ключевыми словами IRP
         и ENDM, будет  повторен  для  каждого  параметра  в  списке,
         заключенном  в  скобках  <>.  Формальный-параметр  относится 
         только к  данному блоку и последовательно принимает значения
         из списка. В качестве параметров в списке могут  быть заданы
         определенные   символы,   строки,   числа   или   символьные
         константы.  Может  быть  задано  любое   число   параметров,
         которые,  если  их  несколько,  должны разделяться запятыми.
         Тело блока может включать в  себя  любые  предложения  языка

                                   - 27 -
         
         
         ассемблера.  Формальный-параметр  в  теле  блока  может быть
         использован произвольное число раз.
               Когда MASM распознает директиву IRP, он  создает копию
         предложений  блока  для  каждого  параметра  в  списке.  При
         копировании  предложений   осуществляется   замена   текущим
         параметром всех вхождений формального параметра блока.  Если
         в  списке  будет  обнаружен пустой параметр (<>), формальный
         параметр   получит  значение   пустой  строки.  Если  список
         параметров пуст, блок игнорируется.
               
               Пример:
               
         alloc MACRO x
               IRP   y,
               DB    y
               ENDM
               ENDM
               
               В результате обработки макровызова
               
               alloc <0,1,2,3>
               
               будет сгенерировано макрорасширение
               
               IRP   y,<0,1,2,3>
               DB    y
               ENDM
               
               
               IRPC-блок имеет следующий формат:
               
               IRPC формальный-параметр,строка
                  ...
                предложения
                  ...
               ENDM
               
               Блок предложений, заключенный между  ключевыми словами
         IRPC  и  ENDM,  будет  повторен для каждого символа указанной
         строки. При этом каждое  вхождение  формального  параметра в
         блоке   замещается   текущим   символом    строки.    Строка
         представляет  собой  любую  комбинацию  букв,  цифр и других
         символов. Если строка содержит пробелы, запятые  или  другие
         ограничители,  она  должна быть заключена в одинарные скобки
         <>. Тело блока может включать в себя любые предложения языка
         ассемблера.  Формальный  параметр  в  теле  блока может быть
         использован произвольное число раз.
               Когда MASM распознает директиву IRPC, он создает копию
         предложений  блока  для  каждого  символа   в   строке.  При
         копировании   предложений   осуществляется   замена  текущим
         символом строки всех вхождений формального параметра блока.
               
               
               
               

                                   - 28 -
         
         
               
               
               
                            5.3. Макрооператоры.
         

               В  качестве  элементов  генерируемого  текста  в  теле
         макроопределения  могут  быть  использованы  макрооператоры,
         приведенные в таблице 5.1.
               
               
                      Таблица 5.1. Макрооператоры.
               
         ___________________________________________________________
         |                        |                                |
         |       синтаксис        |         функция                |
         |________________________|________________________________|
         |                        |                                |
         |  &формальный-параметр  |                                |
         |________________________|       оператор замены          |
         |                        |                                |
         |  формальный-параметр&  |                                |
         |________________________|________________________________|
         |                        |                                |
         |  <текст>               |  текстовый оператор литерала   |
         |________________________|________________________________|
         |                        |                                |
         |  !символ               |  символьный оператор литерала  |
         |________________________|________________________________|
         |                        |                                |
         |  %текст                |       оператор выражения       |
         |________________________|________________________________|
         |                        |                                |
         |  ;;текст               |       макрокомментарий         |
         |________________________|________________________________|
              
               
               Оператор   замены   &   обеспечивает  замену  в тексте
         формального  параметра  на  значение   соответствующего  ему
         фактического    параметра    макроопределения.    Символ   &
         употребляется  как  перед,  так  и  после  имени формального
         параметра и служит для выделения параметра в строке символов
         или в строке, содержащей кавычки.
               Во вложенных  макроопределениях  оператор замены может
         быть использован для задержки замены  формального  параметра
         действительным  значением, для чего используется более общая
         форма оператора замены, в которой символ & может быть указан
         несколько   раз.  MASM  трактует  количество  рядом  стоящих
         символов  &   как   глубину   вложенности   макроопределений
         (относительно   текущего   уровня),   на   которой   следует
         осуществлять замену формального параметра.
               
               Пример:
               
         alloc MACRO x

                                   - 29 -
         
         
               IRP   z,<1,2,3>
         x&&z  DB    z
               ENDM
               ENDM
               
               В  этом  примере   замена   формального  параметра   x
         осуществляется  немедленно  при   вызове   макроопределения.
         Замена параметра z будет задержана до начала обработки блока
         повторения  IRP  с тем, чтобы параметр z получал значения из
         указанного   списка.   Таким   образом,   параметр  z  будет
         замещаться значением элемента списка каждый раз при переходе
         к  следующему  элементу  списка блока повторения. В итоге по
         макрокоманде 
               
               alloc var
               
               будет сгенерировано макрорасширение
               
         var1  DB    1
         var2  DB    2
         var3  DB    3
               
               
               Текстовый  оператор   литерала   указывает  MASM,  что
         заданный внутри скобок < и >  текст  следует  трактовать как
         простой литеральный  элемент независимо от того, содержит ли
         он запятые, пробелы или другие ограничители. Чаще всего этот
         оператор используется  в  макровызовах  и директивах IRP для
         того, чтобы значения  списка  параметров  обрабатывались как
         один параметр.
               Кроме того,  этот оператор используется в тех случаях,
         когда необходимо, чтобы MASM трактовал некоторые специальные
         символы  (например,  ;  или  &)  как  литералы.  Например, в
         выражении <;> точка с запятой  рассматривается  как  точка с
         запятой, а не как начало комментария.
               
               Символьный   оператор   литерала   !   отличается   от
         текстового   лишь   тем,  что  в  нем  в  качестве  литерала
         рассматривается  только  непосредственно  следующий   за   !
         символ. Например, выражения !; и <;> эквивалентны.
               
               Оператор выражения  % указывает MASM, что данный текст
         следует трактовать как  выражение.  MASM  вычисляет значение
         выражения с учетом основания системы счисления встречающихся
         в выражении чисел и замещает  текст  этим  значением.  Текст
         должен представлять корректное выражение.
               Оператор выражения обычно используется в макровызовах,
         когда  в  макроопределение   необходимо   передать  значение
         выражения, а не его текстовую форму.
               
               Пример:
               
         area  MACRO par
               DW    &par
               ENDM

                                   - 30 -
         
         
               
         sum1  EQU   100
         sum2  EQU   200
               
               В результате обработки макровызова
               
               area %(sum1+sum2)
               
               будет сгенерировано макрорасширение
               
               DW    300
               
               
               
               Оператор макрокомментария  ;;  определяет, что остаток
         строки является макрокомментарием.  В  отличие  от  обычного
         комментария,   который   обозначается  одинарными  точкой  с
         запятой  и  также  может  встречаться  в  макроопределениях,
         макрокомментарий  в  текст макрорасширения  не  попадает. Он 
         присутствует лишь в теле макроопределения.


© KOAP Open Portal 2000