Макросы и директивы компилятора FASM | страница 3
>macro movstr
> {
> local move
> move:
> lodsb
> stosb
> test al,al
> jnz move
> }
При использовании этого макроса метка >move
всегда имеет свое уникальное значение и повторение этого макроса не вызовет ошибок.
Директивы >forward
, >reverse
и >common
делят макрос на блоки, каждый обрабатывается после того, как обработка предыдущих закончена. Они отличаются по поведению, только если макрос позволяет множественные группы аргументов. Блок инструкций, что следует за директивой >forward
, будет обработан для каждой группы аргументов с первого до последнего — наподобие обычному блоку (не заданному в соответствии с любой из этих директив). Блок, который следует за директивой >reverse
, будет обработан для каждой группы аргумента в обратном порядке — от последнего до первого. Блок, который следует за директивой >common
, будет обработан только однажды, сразу для всех групп аргументов. Значение >local
, определенное в одном из блоков доступно во всех следующих блоках при обработке той же самой группы аргументов где оно было определено, когда оно определено в блоке >common
, оно доступно во всех следующих блоках независимо какая группа аргументов обрабатывается.
Вот пример макроса, который создаст таблицу адресов к строкам, заданных этими строками:
>macro strtbl name,[string]
> {
> common
> label name dword
> forward
> local label
> dd label
> forward
> label db string,0
> }
Первый аргумент, переданный этому макросу, станет меткой для таблицы адресов, следующие аргументы должны быть строками. Первый блок обрабатывается только один раз и определяет метку, второй блок для каждой строки объявляет ее локальное имя и определяет запись таблицы, содержащую адрес той строки. Третий блок определяет данные каждой строки с соответствующей меткой. Директива, начинающая блок в макросе может сопровождаться первой инструкцией этого блока на той же самой строке, как показано в следующем примере:
>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, это имя будет заменено всеми ее величинами, отделенными запятыми. Например следующий макрос передаст все дополнительные аргументы предварительно заданному макросу