Макроопределением называется набор нескольких команд ассемблера, сгруппированных вместе. Как правило, набор таких команд формируется исходя из законченности некоторого действия, которое эти команды осуществляют все вместе.
Однажды описанный в макроопределении набор команд будет копироваться в текст программы столько раз, сколько раз встречается макрокоманда вызова этого макроопределения. Процесс копирования набора команд из макроопределения в текст программы ассемблера назовется макроподстановкой и производится макрогенератором до начала этапа обработки текста программы транслятором.
Макрокоманда обычно выполняется быстрее аналогичной процедуры, поскольку нет необходимости выполнять переход в тело процедуры и возврат из него. Если уж макроопределение описано, макрокоманда его вызова может встречаться в любом месте программы. Однако одно неудобство в использовании макроопределений: если макрокоманда используется довольно часто, то это приведет к дополнительным затратам памяти по сравнению с вариантом использования процедуры.
Например, последовательность команд
Mov ah,2
Int 21h
приводит к выводу на консоль символа, код которого записан в регистре dl.
Объединение этих команд в макроопределение выглядит следующим образом:
Mputcahr macro
mov ah,2
int 21h
endm
Макроподстановка будет производиться в любом месте программы, где встретится макрокоманда Mputchar.
Важной деталью макроопределений является возможность использования параметров. Недостатком приведенного выше макроопределения является то, что перед использованием этой команды необходимо провести загрузку кода символа в регистр отдельной командой. Но сейчас, если мы введем в макроопределение параметр char, мы сможем указывать код символа в той же строке, в которой располагается макрокоманда:
Mputcahr macro char
puch ax
puch dx
mov ah,2
mov dl,char
int 21h
pop dx
pop ax
endm
Появление в тексте программы макрокоманды Mputchar ’a’, приведет к формированию части программного кода (макрорасширения), результатом исполнения которого будет вывод на экран символа 'a'.
В самом общем виде формат макроопределения можно записать в виде:
Macroname macro argument-1, argument-2,…
список операторов
endm
А вид соответствующей макрокоманды должен быть следующий:
Macroname argument-1, argument-2,…
Здесь Macroname имя макроопределения, описанного в тексте программы, а каждый аргумент является величиной передаваемой в макроопределение и замещающей соответствующий параметр. Операторы, записанные между директивами macro и endm, не рассматриваются компилятором до тех пор, пока ему не встретиться макрокоманда.
Комментарии, которые будут присутствовать в тексте макроопределения и не попадут в макрорасширение, выделяются двумя символами точка с запятой – «;;».
Список формальных аргументов макроопределения в общем случае содержит не только перечисление через запятую имен формальных аргументов, но и их тип, поэтому полное описание формального аргумента имеет следующий вид:
Имя_формального_аргумента[:тип], при этом тип может принимать значения:
· REQ – которое говорит о том, что данный аргумент всегда требует явного указания фактического аргумента при вызове макрокоманды;
· =<любая_строка> - указывает на то, что если при вызове макрокоманды данный фактический аргумент не задан, то макрогенератором будет использоваться значение этого аргумента по умолчанию, записанное в угловых скобках.
Следует иметь в виду так же и то, что макрогенератору не всегда удается без помощи программиста распознать имя формального аргумента внутри текста макроопределения. Дело в том, что формальный аргумент может быть использован как часть некоторого формируемого символьного выражения, поэтому, если просто указать имя аргумента в необходимом контексте, оно обнаружено макрогенератором быть не может. В этом случае программист должен отделить имя аргумента от остального контекста символом &.
Некоторые правила накладываются и на запись фактических аргументов. Если фактическим аргументом является строка без пробелов или разделителей, то она может быть без затруднений воспринята макрогенератором как фактический аргумент. Но может оказаться и так, что фактический аргумент должен содержать пробел. В этом случае фактический аргумент должен быть указан внутри угловых скобок (<>). Если в строке встречается какой-либо специальный символ, который может тем или иным образом быть истолкован макрогенератором как символ управления, то действие такого символа можно экранировать с помощью знака «!».
Иногда в качестве значения фактического аргумента требуется передать значение некоторого вычисляемого константного выражения. И в этом случае фактический аргумент должен иметь какой-то отличительный признак от символьного выражения, иначе именно оно будет рассматриваться как фактический аргумент. Поэтому, если в качестве аргумента должно использоваться вычисленное значение, перед символьным выражением, определяющим этот значение, должен быть написан символ «%».
Например, для формирования массива в памяти можно воспользоваться макроопределением:
Marray macro name,size,type:=<b>
name d&type size dup(0)
endm
В результате использования макрокоманд:
Marray array1,10
P equ 10
Q equ 2
Marray array2,%P*Q,w
будут сформированы строки:
array1 db 10 dup(0)
array2 dw 20 dup(0)
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.