4. Простые макросы без аргументов

4.1. Определение простых макросов

Использую

EQU
можно делать наиболее простые замены в исходном тексте при обработке препроцессором. Большими возможностями обладают макросы. Командой
MACRO
можно создавать собственные инструкции.

Синтаксис:

macro name

{

; тело макроса

}

Когда препроцессор находит директиву

macro
, он определяет макрос с именем
name
. Далее, встретив в исходном тексте строку, начинающуюся с
name
, препроцессор заменит
name
на тело макроса — то, что указано в определении между скобочками
{
и
}
. Имя макроса может быть любым допустимым идентификатором, а тело макроса — всё, что угодно, за исключением символа
}
, который означает завершение тела макроса.

Например:

macro a

{

 push eax

}

xor eax, eax

 a

будет заменено на:

xor eax, eax

push eax

Или:

macro a

{

 push eax

}

macro b

{

 push ebx

}

b

a

получим:

push ebx

push eax

Разумеется, макросы не обязательно оформлять так, как выше, можно делать и так:

macro push5 {push dword 5}

push5

получим:

push dword 5

Или:

macro push5 {push dword 5

}

с тем же самым результатом. Скобочки можете размещать как хотите.

4.2. Вложенные макросы

Макросы могут быть вложенными один в другой. То есть, если мы переопределим макрос, будет использовано последнее определение. Но если в теле нового определения содержится тот же макрос, то будет использовано предыдущее определение. Посмотрите пример:

macro a {mov ax, 5}

macro a

{

 a

 mov bx, 5

}

macro a

{

 a

 mov cx, 5

}

a

в результате получим:

mov ax, 5

mov bx, 5

mov cx, 5

Или такой пример:

macro a {1}

a

macro a {

 a

 2 }

a

macro a {

 a

 3 }

a

получим:

1

1

2

1

2

3

4.3. Директива PURGE. Отмена определения макроса

Как и в случае с директивой

EQU
, можно отменить определение макроса. Для этого используется директива
PURGE
с указанием имени макроса.

Синтаксис:

purge name

Пример:

a

macro a {1}

a

macro a {2}

a

purge a

a

purge a

a

получим:

a

1

2

1

a

Если применить

PURGE
к несуществующему макросу, ничего не произойдёт.

4.4. Поведение макросов

Имя макроса будет заменено его телом не только в том случае, если оно расположено в начале строки. Макрос может находиться в любом месте исходного текста, где допустима мнемоника инструкции (например,

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

}

Загрузка...