Читать «Assembler. Программирование на языке ассемблера IBM PC» онлайн - страница 143
Unknown Author
Отметим, что в ЯА допускается вложенность макроопределений, например:
ARR2 MACRO Х1,Х2,К ARR MACRO X,N
X DB N DUP(?) ENDM
ARR X1,<K> ARR X2,<K> ENDM
Однако при этом надо учитывать следующее. Макрос ARR, хотя и описан внутри макроса ARR2, не локализуется в ARR2, и к нему можно обращаться вне макроса ARR2. Но ассемблер работает так, что описание внутреннего макроса он ’’замечает” только при первом обращении к внешнему макросу. Поэтому обращаться к макросу ARR до обращения к макросу ARR2 нельзя:
ARR А,50 ARR2 В,С,100 ARR D,60
(имя ARR еще ие описано
;можно (имя ARR уже описано)
IU.7. Директива LOCAL
При использовании макросов возникает неприятная проблема с метками, которыми могут быть помечены предложения тела макроса. Пусть, к примеру, имеется макрос со следующей структурой:
м MACRO
# # #
Li • • •
ENDM
и пусть в программе имеется два обращения к этому макросу. Тогда после макроподстановок мы получим следующую картину:
М L: ...
# # • • Ф •
М L: ...
Как видно, в окончательном тексте программы появились две команды, помеченные одной и той же меткой L, а это ошибка. Почему так произошло? Дело в том, что имя L не является формальным параметром макроса и потому при макроподстановке ни на что не заменяется, а переносится в макрорасширение без всяких изменений. Вот и получается, что в окончательном тексте программы будет столько меток L, сколько было обращений к данному макросу.
Как избежать этой ошибки? Возможный вариант - включить метку L в число параметров макроса и при обращении к макросу указывать различные фактические метки. Однако это плохое решение, поскольку метки, которыми метятся команды тела макроса, - это чисто внутреннее дело макроса, и для того, кто будет пользоваться этим макросом, нет никакого дела до этих меток, придумывать имена для таких внутренних меток - это лишняя работа.
Учитывая это, в ЯА предложено иное, более удобное решение данной проблемы. Оно заключается в том, что после заголовка макроса (директивы MACRO) надо указать специальную директиву макроязыка:
LOCAL vl
vk
(k>=l)
где vi - имена, используемые в макроопределении (обычно это метки). Тогда при макроподстановке макрогенератор будет заменять эти имена на специальные имена вида ??хххх, где хххх - четырехзначное шестнадцатеричное число, т. е. на имена ??0000, ??0001 и так далее до ??FFFF. Правила такой замены следующие.
Макрогенератор запоминает номер, который он использовал в последний раз; пусть это был номер п. Когда макрогенератор встречает обращение к макросу, в котором имеется директива LOCAL, то он ставит в соответствие именам, перечисленным в этой директиве, специмена с очередными номерами: специмя ??(п+1) для vl, специмя ??(п+2) для v2 и т. д., а затем при макроподстановке заменяет каждое вхождение vi на одно и то же специмя ??(n+i). Когда макрогенератор встретит новое обращение к этому же или другому макросу, где есть директива LOCAL, то он будет уже использовать специмена с последующими номерами: n+k+1 и т. д. Поэтому в разных макрорасширениях появятся разные специмена, совпадений не будет.