Flat Assembler 1.64. Мануал программера | страница 20



>macro movstr

>{

> local move

> move:

> lodsb

> stosb

> test al,al

> jnz move

>}

Каждый раз, когда используется эта макроинструкция, «>move» заменяется новым уникальным именем. То есть вы не получите ошибку, это обычный случай, когда метка определяется больше, чем один раз.

«>forward», «>reverse» и «>common» делят макроинструкцию на блоки, каждый из которых обрабатывается после окончания обработки предыдущего. Они различаются в поведении только если макроинструкция поддерживает много групп аргументов. Блок инструкций, следующий за «>forward» будет обрабатываться для каждой группы аргументов от первой до последней, как блок по умолчанию (без этих директив). Блок, идущий за «>reverse» будет обрабатываться для каждой группы аргументов в обратном порядке — от последней до первой. Блок за директивой «>common» обрабатывается лишь один раз, просто для всех групп аргументов. Локальное имя, определенное в одном блоке, доступно во всех следующих блоках при обработке той же группы аргументов. Если оно было определено в блоке «>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», оно будет заменено на все значения, разделенные запятыми. Например, следующий макрос передать все дополнительные аргументы ранее определенной макроинструкции «