<p>4.4. Поведение макросов</p>

Имя макроса будет заменено его телом не только в том случае, если оно расположено в начале строки. Макрос может находиться в любом месте исходного текста, где допустима мнемоника инструкции (например, add или mov). Всё потому, что основное предназначение макросов — имитировать инструкции. Единственное исключение из этого правила — макросы недопустимы после префиксов инструкций (rep).

Пример:

macro CheckErr

{

 cmp eax, -1

 jz error

}

 call Something

a: CheckErr ; здесь макросу предшествует метка, всё Ок.

получим:

 call Something

a: cmp eax,-1

 jz error

Пример № 2:

macro stos0

{

 mov al, 0

 stosb

}

 stos0       ;это место инструкции, будет замена.

here: stos0  ;это тоже место инструкции.

 db stos0    ;здесь инструкции не место, замены не будет.

получим:

 mov al, 0

 stosb

here: mov al, 0

 stosb

 db stos0

Возможно переопределять (overload) инструкции посредством макросов. Так как препроцессор ничего об инструкциях не знает, он позволяет использовать мнемонику инструкции в качестве имени макроса:

macro pusha

{

 push eax ebx ecx edx ebp esi edi

}

macro popa

{

 pop edi esi ebp edx ecx ebx eax

}

эти 2 новые инструкции будут экономить по 4 байта в стеке, так как не сохраняют ESP (правда, занимают побольше места, чем реальные инструкции:). Всё же, переопределение инструкций не всегда хорошая идея — кто-нибудь читая Ваш код может быть введён в заблуждение, если он не знает, что инструкция переопределена.

Также, возможно переопределять директивы ассемблера:

macro use32

{

 align 4

 use32

}

macro use16

{

 align 2

 use16

}

<p>5. Макросы с фиксированным количеством аргументов</p><p>5.1. Макросы с одним аргументом</p>

Макросы могут иметь аргумент. Аргумент представляет собой какой-либо идентификатор, который будет повсюду заменён в теле макроса тем, что будет указанно при использовании.

Синтаксис:

macro name argument { тело макроса }

Например:

macro add5 where

{

 add where, 5

}

add5 ax

add5 [variable]

add5 ds

add5 ds+2

получим:

add ax, 5

add [variable], 5

add ds, 5  ;такой инструкции не существует

           ;но препроцессор это не волнует.

           ;ошибка появится на стадии ассемблирования.

add ds+2,5 ;ошибка синтаксиса, как и ранее

           ;определится при анализе синтаксиса (parsing).

(разумеется, комментарии в результате работы препроцессора не появятся:)

<p>5.2. Макросы с несколькими аргументами</p>

У макросов может быть несколько аргументов, разделённых запятыми,

macro movv where, what

{

 push what

 pop where

}

movv ax, bx

movv ds, es

movv [var1], [var2]

преобразуется в:

push bx

pop ax

push es

pop ds

push [var2]

pop [var1]

Если несколько аргументов имеют одно и тоже имя, то будет использован первый из них:).

Если при использовании макроса указать меньше аргументов, чем при определении, то значения неуказанных будет пустым:

macro pupush a1, a2, a3, a4

{

 push a1 a2 a3 a4

 pop a4 a3 a2 a1

}

pupush eax, dword [3]

получим:

push eax dword [3]

pop dword [3] eax

Если в аргументе макроса необходимо указать запятую, необходимо аргумент заключить в скобочки из символов < и >.

macro safe_declare name, what

{

 if used name

  name what

 end if}

safe_declare var1, db 5

safe_declare array5,

safe_declare string,

получим:

if used var1

 var1 db 5

end if

if used array5

 array5 dd 1,2,3,4,5

end if

if used string

 string db "привет, я просто строка",0

end if

Конечно же, можно использовать символы < и > и внутри тела макроса:

macro a arg {db arg}

macro b arg1,arg2 {a }

b <1,1>,2

получим:

db 1,1,2,3

<p>5.3. Директива LOCAL</p>

Возможно, появится необходимость объявить метку внутри тела макроса:

macro pushstr string

{

Перейти на страницу:

Похожие книги