Первый аргумент, задаваемый этой макроинструкции, станет меткой для таблицы адресов, следующими аргументами должны быть строки. Первый блок обрабатывается однажды и определяет метку, второй блок назначает локальную метку для каждой строки и определяет запись в таблице, содержащий адрес этой строки. Третий блок определяет данные каждой строки с соответствующей меткой.
Первая инструкция, следующая за директивой, начинающей блок в макроинструкции, может идти с ней на той же строке, как на следующем примере:
macro stdcall proc,[arg]
{
reverse push arg
common call proc
}
Это макрос может применяться для вызова процедур, используя соглашение STDCALL, аргументы сохраняются в стеке в обратном порядке. Например, «stdcall foo,1,2,3
push 3
push 2
push 1
call foo
Если некоторое имя внутри макроинструкции имеет несколько значений (это либо один из аргументов, заключенных в квадратные скобки, либо локальное имя, определенное в блоке, следующем за директивой «forward
reverse») и используется в блоке, следующем за директивой «common», оно будет заменено на все значения, разделенные запятыми. Например, следующий макрос передать все дополнительные аргументы ранее определенной макроинструкции «stdcall»:macro invoke proc,[arg]
{ common stdcall [proc],arg }
Он может применяться для непрямого вызова (через указатель в памяти) процедуры, используя соглашение STDCALL.
Внутри макроинструкции также может быть использован специальный оператор «#
cond»:macro jif op1,cond,op2,label
{
cmp op1,op2
j#cond label
}
Например, «jif ax,ae,10h,exit
cmp ax,10h» и «jae exit».Оператор «#
Возможно преобразование имени в строку в кавычках с помощью оператора «`
`» конвертирует только символ, идущий непосредственно за ним. Здесь пример использования этих двух свойств:macro label name
{
label name
if ~ used name
display `name # "is defined but not used.",13,10
end if
}
Если метка, определенная таким макросом, не используется в коде, он известит вас об этом сообщением, указывающим, к какой метке это относится.
Чтобы создать макроинструкцию, ведущую себя по-разному в зависимости от типа аргументов, например если это строки в кавычках, вы можете использовать оператор сравнения «eqtype
macro message arg
{
if arg eqtype ""
local str
jmp @f
str db arg,0Dh,0Ah,24h
@@:
mov dx,str
else
mov dx,arg
end if
mov ah,9
int 21h
}
Вышеописанный макрос создан для показа сообщений в программах DOS. Если аргумент этого макроса некоторое число, метка или переменная, показывается строка из этого адреса, но если аргумент — это строка в кавычках, то созданный код покажет её после … и … .
Также возможно объявить макроинструкцию внутри другой макроинструкции, то есть один макрос может определить другой, но с такими определениями есть проблема, вызванная тем, что знак «}
\{» трактуется как один символ, но во время обработки макроса он станет символом «\{». Это позволит вам определить одну макроинструкцию внутри другой:macro ext instr
{
macro instr op1,op2,op3
\{
if op3 eq
instr op1,op2
else
instr op1,op2
instr op2,op3
end if
\}
}
ext add
ext sub