Читать «Assembler. Программирование на языке ассемблера IBM PC» онлайн - страница 135
Unknown Author
Рассмотрим следующий блок повторения и построенные по нему копии:
IRP W,<VAR1,VAR6> VAR1 DW ?
W DW ? -^ VAR6 DW ?
ENDM
Здесь параметр W обозначает имя переменной целиком. Но фактические имена (VAR1 и VAR6) различаются лишь последним символом, поэтому было бы разумнее объявить параметром только этот символ, а не все имя. Но если так и сделать:
IRP W,<1,6>
VARW DW ?
ENDM
то получится неоднозначность: становится непонятным, когда W обозначает формальный параметр, а когда саму букву W (почему в VARW надо W заменять на 1 и 6, а в DW не надо?). Во всех предыдущих примерах мы не сталкивались с такой проблемой, т. к. формальные параметры легко выделялись из окружающего текста благодаря ограничителям (пробелам, запятым и т. п.), стоящим слева и справа от них. Но если рядом с параметром стоит имя или число, то границы параметра становятся неопределяемыми. В подобной ситуации следует между параметром и соседним с ним числом или именем поставить символ & (A&W, 1&W&B и т. п.). Например, наш блок повторения должен быть записан следующим образом:
IRP И,<1,6>
VAR&W DW ?
ENDM
Назначение знака & - указать границу формального параметра, выделить его из окружающего текста, при этом в окончательный текст программы он не попадает. (Если & поставить не около параметра, то он будет просто опущен.)
Макрооператор & используется не только тогда, когда формальный параметр "сливается" с соседними именами и числами, но и когда его надо указать внутри строк. Дело в том, что макрогенератор игнорирует вхождения формального параметра в строки, и чтобы обратить его внимание на эти вхождения, перед параметром в строках надо ставить знак & (а если не ясна его правая граница, то & надо указывать и после параметра). Например:
IRPC А,и< DB 'А,","В'
DB 'А,&А,&А&В' DB 'А,<,<В'
ENDH
И еще одна особенность макрооператора &: если рядом поставить несколько знаков &, то макрогенератор удалит только один из них. Это сделано специально, учитывая возможность вложенности блоков повторений (и/или макросов). Например:
IRPC Р1,АВ IRPC P2,HL INC Р1&4Р2 ENDM
endm
IRPC P2,HL INC A&P2 ENDM
IRPC P2,HL INC B&P2 ENDM
INC AH INC AL INC BH INC BL
Встретив в тексте исходной программы блок повторения, указанный в левой колонке, макрогенератор сначала создаст первую копию тела внешнего блока, в котором все вхождения его формального параметра Р1 будут заменены на символ А (err. три верхние строчки средней колонки). При этом из двух подряд стоящих в команде INC знаков & будет удален только один, и оставшийся знак & будет отделять формальный параметр Р2 внутреннего блока от стоящей слева
буквы А (если бы был только один знак &, то эта команда имела бы вид INC АР2, и потому запись АР2 не воспринималась бы как состоящая из двух частей - А и Р2). Поскольку в полученной копии остались’ конструкции макроязыка, то макрогенератор продолжает свою работу (это общее правило: макрогенератор работает, пока не получится текст на "чистом" языке ассемблера) и "раскручивает" внутренний блок, получая уже окончательный текст (см. две верхние строчки в правой колонке). Далее создается вторая копия внешнего блока, которая обрабатывается аналогично.