В обработке макрокоманд применяется одно из ценных свойств  процедур: в генерацию макрокоманды можно вносить изменения с  помощью параметров. Точно так же, как параметры подпрограммы могут  влиять на ее выполнение, параметры макрокоманды определяют  фактически генерируемые команды. И так же, как и процедуры,  макрокоманды без параметров встречаются относительно редко.

Рассмотрим еще один простой пример. Мы составили программу так,  что во многих ее местах содержимое определенной ячейки памяти  складывается с различными константами. Вместо того, чтобы много раз  писать команду

  ADD MEMORY_BYTE,5

или

  ADD MEMORY_BYTE,7

нам хотелось бы воспользоваться для нее соответствующей  макрокомандой. Однако во всех приведенных командах константы разные. Поэтому мы сделаем константу параметром макрокоманды. На  Фиг. 6.2 показаны определение и применение макрокоманды ADDBYTE. В  этом примере в качестве параметра в определении макрокоманды  используется символическое имя CONSTANT. Любые символические имена,  появляющиеся в поле операнда оператора MACRO, интерпретируются как  параметры. В момент определения макрокоманды у имени CONSTANT нет  никакого значения: оно просто резервирует место в тексте  макрокоманды. Позднее, при вызове и обработке текста макрокоманды,  вместо символического имени в определении макрокоманды  подставляется определенное значение параметра.  Важно отметить, что параметр макрокоманды - это текстовый  параметр. Так как макропроцессор фактически является текстовым  процессором, то он не отличает цифры от букв и наоборот. Это  позволяет при вызове макрокоманды использовать вместо чисел  символические имена. Любой смысл приписывается символьной строке не  макропроцессором, а ассемблером. Макропроцессор подставляет
          Microsoft (R) Macro Assembler Version 5.00              1/1/80 04:02:43

           Фиг. 6.2 Макрокоманда с аргументом                Page         1-1

 

                                          PAGE   ,132

                                          TITLE  Фиг. 6.2 Макрокоманда с аргументом

 

                                    ADDBYTE MACRO   CONSTANT

                                          ADD    MEMORY_BYTE, CONSTANT

                                          ENDM

 

            0000                   CODE   SEGMENT

                                          ASSUME CS:CODE

 

            0000  ??               MEMORY_BYTE     DB     ?

 

            = 0004                       FOUR        EQU    4         ; Симвользое изображение константы

 

                                          ADDBYTE           2

            0001  2E: 80 06 0000 R 02   1            ADD    MEMORY_BYTE, 2

                                          ADDBYTE           4

            0007  2E: 80 06 0000 R 04   1            ADD    MEMORY_BYTE, 4

                                          ADDBYTE           FOUR

            000D  2E: 80 06 0000 R 04   1            ADD    MEMORY_BYTE, FOUR

 

            0013                   CODE   ENDS

                                          END

  Фиг. 6.2 Аргументы макрокоманды

текстовую строку из вызова макрокоманды на место символического  имени в определении макрокоманды. Таким образом программа может  использовать константное значение "FOUR" с тем же успехом, что и  константу "4".

Возможность использовать символические имена в качестве  параметров макрокоманд принципиально важна для следующего примера  макрокоманды. Этой макрокоманда, одной из команд сопроцессора 8087,  требуется параметр, который при обычном ее использовании почти  всегда бывает символическим именем. Макрокоманда FLDCW - это  команда сопроцессора 8087, которая задает ячейку памяти. Так как в  программах на языке ассемблера в большинстве случаев обращаются к  ячейкам памяти с помощью символических имен, то желательно  сохранить этот способ и для программирования сопроцессора 8087.

На Фиг.6.3 приводится макрокоманда FLDCW и несколько обращений  к ней. Заметьте, что макрокоманда FLDCW использует в качестве  параметра символическое имя "SOURCE". Параметр SOURCE является  адресом, с которого сопроцессор 8087 загружает управляющее слово.  Для генерации требуемого машинного кода макрокоманда FLDCW  использует команду 8088 ESC. Однако для того, чтобы определить байт  mod=r/m команды, команде ESC требуется значение адреса. Как раз для

            Microsoft (R) Macro Assembler Version 5.00              1/1/80 04:02:47

            Фиг. 6.3 Макрокоманда для команды FLDCW                 Page    1-1


                                           PAGE   ,132

                                           TITLE  Фиг. 6.3 Макрокоманда для команды FLDCW

 

                                     FLDCW  MACRO   SOURCE

                                           DB     09BH

                                           ESC    0DH, SOURCE

                                           ENDM

 

            0000                     CODE   SEGMENT

                                           ASSUME CS:CODE

 

            0000  ????               MEMORY_LOCATION DW      ?

 

                                           FLDCW  MEMORY_LOCATION

            0002  9B              1        DB     09BH

            0003  2E: D9 2E 0000 R      1        ESC    0DH, MEMORY_LOCATION

                                           FLDCW  ES:[DI]

            0008  9B              1        DB     09BH

            0009  26: D9 2D       1        ESC    0DH, ES:[DI]

                                           FLDCW  MEMORY_LOCATION[BX+SI]

            000C  9B              1        DB     09BH

            000D  2E: D9 A8 0000 R      1        ESC    0DH, MEMORY_LOCATION[BX+SI]

 

            0012                     CODE   ENDS

                                           END

  Фиг. 6.3. Макрокомнда FLDCW

этого макрокоманда и использует параметр SOURCE. Такая организация  макрокоманды FLDCW позволяет программировать весьма естественным  способом. Точно так же как пишется

  INC MEMORY_LOCATION

вы можно написать команду для сопроцессора 8087

  FLDCW MEMORY_LOCATION

Это справедливо не только для адресов, заданных символическими  именами, но и для других способов адресации. На Фиг. 6.3 показано  несколько примеров задания операнда с помощью адресации по базе и  индексу. Так как макропроцессор воспринимает параметр как какой-то  фрагмент текста, то параметр может быть образован любой символьной  строкой, какую вы пожелаете.

Можно задать макрокоманду и с несколькими параметрами.  Единственное, что ограничивает число параметров макрокоманды, это  длина ассемблерной строки. Все, что следует за оператором MACRO  интерпретируется макропроцессором как параметр. Для разделения  символических имен в определении макрокоманды пользуются запятыми.  Оператор MACRO с тремя параметрами будет выглядеть следующим  образом:

  EXAMPLE MACRO ARG1, ARG2, ARG3

Аналогично, при вызове макрокоманды вы должны задать значение  каждого из параметров. Если вы хотите пропустить какой-то параметр,  то ассемблер подставит вместо него символьную строку нулевой длины.  Иногда это полезно, но часто приводит к неправильной трансляции.  Если макрокоманда имеет более одного параметра, то при вызове  макрокоманды относящийся к параметрам текст разделяется запятыми.  Это в точности совпадает со способом задания нескольких параметров  к любой из команд микропроцессора 8088, поэтому будет вполне  естественным для вас. Вызов макрокоманды с тремя параметрами может  выглядеть так:

  EXAMPLE 5, [BX], MEMORY_BYTE

В следующем примере вы увидите некоторые возможности множественности параметров.