|
В обработке макрокоманд применяется одно
из ценных свойств
процедур: в генерацию макрокоманды можно
вносить изменения с
помощью параметров. Точно так же, как
параметры подпрограммы могут
влиять на ее выполнение, параметры
макрокоманды определяют
фактически генерируемые команды. И так же,
как и процедуры,
макрокоманды без параметров встречаются
относительно редко.
Рассмотрим еще один простой пример. Мы
составили программу так,
что во многих ее местах содержимое
определенной ячейки памяти
складывается с различными константами.
Вместо того, чтобы много раз
писать команду
ADD MEMORY_BYTE,5
или
ADD MEMORY_BYTE,7
нам хотелось бы воспользоваться для нее
соответствующей
макрокомандой. Однако во всех приведенных
командах константы
разные. Поэтому мы сделаем константу
параметром макрокоманды. На
Фиг. 6.2 показаны определение и применение
макрокоманды ADDBYTE. В
этом примере в качестве параметра в
определении макрокоманды
используется символическое имя CONSTANT.
Любые символичесике имена,
появляющиеся в поле операнда оператора
MACRO, интерпретируются как
параметры. В момент определения
макрокоманды у имени CONSTANT нет
никакого значения: оно просто резервирует
место в тексте
макрокоманды. Позднее, при вызове и
обработке текста макрокоманды,
вместо символического имени в определении
макрокоманды
подставляется определенное значение
параметра.
Важно отметить, что параметр макрокоманды
- это текстовый
параметр. Так как макропроцессор
фактически является текстовым
процессорорм, то он не отличает цифры от
букв и наоборот. Это
позволяет при вызове макрокоманды
использовать вместо чисел
символические имена. Любой смысл
приписывается символьной строке не
макропроцессором, а ассемблером.
Макропроцессор подставляет
Microsoft (R) Macro Assembler Version 5.001/1/80 04:02:43
Фиг. 6.2 Макрокоманда с аргументомPage1-1
PAGE,132
TITLEФиг. 6.2 Макрокоманда с аргументом
ADDBYTE MACROCONSTANT
ADDMEMORY_BYTE, CONSTANT
ENDM
0000CODESEGMENT
ASSUMECS:CODE
0000?? MEMORY_BYTEDB?
= 0004FOUREQU4 ; Симвользое изображение константы
ADDBYTE2
00012E: 80 06 0000 R 021ADDMEMORY_BYTE, 2
ADDBYTE4
00072E: 80 06 0000 R 041ADDMEMORY_BYTE, 4
ADDBYTEFOUR
000D2E: 80 06 0000 R 041ADDMEMORY_BYTE, FOUR
0013CODEENDS
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.001/1/80 04:02:47
Фиг. 6.3 Макрокоманда для команды FLDCWPage1-1
PAGE,132
TITLEФиг. 6.3 Макрокоманда для команды FLDCW
FLDCWMACROSOURCE
DB09BH
ESC0DH, SOURCE
ENDM
0000CODESEGMENT
ASSUMECS:CODE
0000????MEMORY_LOCATION DW?
FLDCWMEMORY_LOCATION
00029B1DB09BH
00032E: D9 2E 0000 R1ESC0DH, MEMORY_LOCATION
FLDCWES:[DI]
00089B1DB09BH
000926: D9 2D 1ESC0DH, ES:[DI]
FLDCWMEMORY_LOCATION[BX+SI]
000C9B1DB09BH
000D2E: D9 A8 0000 R1ESC0DH, MEMORY_LOCATION[BX+SI]
0012CODEENDS
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
Вследующем
примере вы увидите некоторые возможности множествен-
ности параметров.
|