Читать «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 и т. д. Поэтому в разных макрорасширениях появятся разные специмена, совпадений не будет.