test_mac <'two','three','four'> <-- 2-ой вызов
2 db 'two' ;добавить элемент
2 db 'three' ;добавить элемент
2 db 'four' ;добавить элемент
------------------------------------------------------------------
При каждом проходе блока повторения в качестве значения dummy
используется очередное значение списка аргументов. Используя ди-
рективу IRP, мы можем для выполнения трех действий применить
только один вызов макро. При повторном вызове test_ mac блок IRP
повторяется db раз для каждой из трех строк списка аргументов.
Введем для макросов два специальных символа - угловые скобки
(< и >). Макро test_mac предполагает наличие только одного аргу-
мента, а мы хотим переслать ему список аргументов. Угловые скобки
выполняют эту функцию, преобразуя текст, заключенный в них, в
одиночный литерал. Таким образом, 'two','three','four' интерпре-
тируется как один аргумент, а не три. Однако сами угловые скобки
принимающему макро не пересылаются. Внутри test_mac args имеет
значение 'two','three','four', а не <'two','three','four'>. Вот
почему в директиве IRP были добавлены угловые скобки.
Однако это объяснение не применимо к строкам! Одиночные кавыч-
ки, в которые заключаются строки, не допускаются, а добавление
еще одного уровня приводит к путанице . Если мы используем опера-
тор define byte (определить байт) так:
db 'dummy' ;добавить элемент
MASM разворачивает строку следующим образом:
2 db 'dummy' ;добавить элемент
что может создать нам довольно много значений dummy, но не
- 1-13 -
сделает то, что мы хотим. Мы можем вызвать использование дей-
ствительного аргумента через
db '&dummy' ;добавить элемент
но MASM развернет эту строку в
2 db "one" ;добавить элемент
Это приведет к появлению специальной ошибки "Чтение текста
после конца". Такая же ошибка возникает, если Вы случайно создали
бесконечный рекурсивный вызов макро. В общем случае MASM выберет
всю память для сохранения всех используемых символов. Будьте вни-
мательны! Это сообщение об ошибке выдается до тех пор, пока Вы не
прекратите работу MASM, нажав "Cоntrоl-C".
Резюме по использованию макро
Из того , что мы изучили, видно - макросы используют некоторый
тип "стенографического" программирования. Так, если вы определили
некоторый блок программы, Вы можете включать его многократно че-
рез простой вызов макро. Мы видели, что макросы определяются при
помощи оператора MACRO, который присваивает макро имя и дополни-
тельно может снабжать его аргументами. Макроописание заканчивает-
ся оператором ENDM. После выполнения макроописания вызов макро
осуществляется по его имени, за которым могут следовать некоторые
параметры.
Мы также видели, как MASM, используя директиву LOCAL, может
вырабатывать уникальные метки и как применяются директивы повто-
рения. Наши знания о директивах повторения и их использовании бу-
дут расширены в следующей главе.
Справочное Руководство Программиста для Операционной Системы
MS-DOS фирмы Майкрософт содержит макроописания всех системных вы-
зовов. Кроме того, в нем также содержатся некоторые основные мак-
росы, предназначенные для решения общих задач (например, переме-
щение строки). Это руководство является хорошим пособием по
применению макросов и их структурированию. Ниже приводятся три
таблицы, которые наверняка окажутся Вам полезными. В Табл. 1-1
приводится свод макродиректив, используемых MASM. В Табл. 1-2 пе-
речисляются специальные макрооператоры; а в Табл. 1-3 собраны
макродирективы управления листингом.
Теперь мы прошли полпути в изучении макросов для структуриро-
ванных программ. Для выполнения работы по созданию этих макросов
нам необходимо знать, когда и что ассемблируется в программу. Это
тема следующего раздела.
Условное ассемблирование
При написании программ на Ассемблере очень неплохо иметь воз-
можность включения некоторых программных секций. Используя макро-
команды, было бы также неплохо иметь возможность выбирать различ-
ные направления работы программы в зависимости от аргументов,
передаваемых в макро. MASM обеспечивает эти возможности через ус-
ловное ассемблирование.
- 1-14 -
Когда может потребоваться условное ассемблировние? Предполо-
жим, что Вы пишите большую программу, которая, подобно большинс-
тву таких программ, имеет какие-то ошибки. Для выяснения обстоя-
тельств работы программы Вы решаете поместить в нее некоторые
отладочные операторы. Однако , когда у Вас появится уверенность,
что программа выполняется правильно, Вы захотите изъять эти опе-
раторы, чтобы программа выполнялась без лишних кодов. Но так как
программа, вероятно, содержит еще много ошибок, отладочные опера-
торы придется выполнять снова. Добавление и удаление операторов
утомительно. Для решения этой проблемы может быть использовано
условное ассемблирование. В Листинге 1-6 показано воздействие пе-
реключателя "DEBUG" (отладить) на операторы блока при условном
ассемблировании. Реализован хороший способ редактирования прог-
раммы, а переключатель .SALL использован для подавления некоторой
части макрорасширения @TypeStr. Наш интерес обращен только к
строкам, связанным с условным ассемблированием.
Таблица 1-1. Макродирективы
--------------------------------------------------------
Директива Переменная Описание применения
--------------------------------------------------------
mname MACRO parameter_list МАКРООПИСAHИЕ
Сигнализирует о нача-
ле блока макроописа-
ния; parameter_list
определяет формальные
аргументы, используе-
мые в блоке.
ENDM КОНЕЦ МАКРО
Сигнализирует конец
макроописания или бло-
ка повторения REPT,IRP
или IRPC. Наличие обя-
зательно!
EXITM ВЫХОД ИЗ МАКРО
При достижении выход из
макро. Наиболее часто
используется при ус-
ловном ассемблировании.
LOCAL symbol_list ЛОКАЛЬНЫЙ СИМВОЛ
Определяет для ассембле-
ра символы из списка
symbol_list как уникаль-
ные символы.
Расширяется в ??ххх, где
ххх - шестнадцатиричные
числа.
PURGE macro_list УДАЛИТЬ МАКРООПИСAHИЕ
Уничтожает описание макро
из списка macro_list.
- 1-15 -
--------------------------------------------------------
Директива Переменная Описание применения
--------------------------------------------------------
REPT выражение ПОВТОРИТЬ
Повторяет блок команд,
размещенных между REPT
и ENDM,столько раз,сколь-
ко задано в выражении.
ITP dummy, НЕОГРAHИЧЕННОЕ ПОВТОРЕНИЕ
Повторяет блок команд
между IRP и ENDM для
каждого значения из para-
meter_list,заменяя фор-
мальный параметр (dummy)на
значение параметра из каж-
дого расширения.
IRPC dummy, строка СИМВОЛ НЕОГРAHИЧЕННОГО
ПОВТОРЕНИЯ
Повторяет блок команд
между IRPC и ENDM для
каждого символа строки,
заменяя формальный пара-
метр на символ из каж-
дого расширения.
---------------------------------------------------------
Таблица 1-2. Специальные символы в макрокомандах
---------------------------------------------------------
Символ Описание применения
---------------------------------------------------------
&argument Соединяет формальные аргументы или сим-
волы с текстом. Особенно необходим для
подстановки вместо формальных аргументов
в строках, заключенных в кавычки.
;;comment text Обозначает комментарий. Такой
комментарий никогда не приводится в
макроописании.
!char Указывает, что следующий далее символ
является литералом. Используется для
включения &, % и т.д. в макрорасширения,
когда эти символы могут быть интерпре-
тированы не как специальные.
%symbol Используется для преобразования символа
или выражения в число текущей системы
счисления.
Угловые скобки (< и >) используются для
определения текста, заключенного между
ними, как литерала. Все, что заключено
в такие скобки, может быть передано в