Руководство по препроцессору FASM - страница 2
>
>mov ecx, count
преобразуется в:
>mov eax, count
>mov ecx,10
потому что препроцессор заменит >count
только после директивы >equ
.
Даже это работает:
>10 equ 11
>mov ecx, 10
после обработки препроцессором, получим:
>mov ecx, 11
Обратите внимание, >name1
может быть любым идентификатором. Идентификатор — это всего лишь набор символов, завершаемый пробелом (space), символом табуляции (tab), концом строки (EOL), комментарием >;
, символом переноса строки >\
или оператором, включая операторы ассемблера и/или специальные символы вроде >,
или >}
.
>name2
может быть не только единичным идентификатором, берутся все символы до конца строки. >name2
может и отсутствовать, тогда >name1
будет заменен на пустое место.
Например:
>10 equ 11, 12, 13
>db 10
получим:
>db 11, 12, 13
3.2. Директива RESTORE
Можно заставить препроцессор прекратить заменять идентификаторы, определённые директивой >EQU
. Это делает директива >RESTORE
.
Синтаксис:
>restore name1
>name1
— это идентификатор определённый ранее в директиве >EQU
. После этой команды name больше не будет заменяться на >name2
.
Например:
>mov eax, count
>count equ 10
>mov eax, count
>restore count
>mov eax, count
получим:
>mov eax, count
>mov eax, 10
>mov eax, count
Обратите внимание, что для определений сделанных директивой >EQU
работает принцип стека. То есть, если мы два раза определим один и тот же идентификатор используя >EQU
, то после однократного использования >RESTORE
значение идентификатора будет соответствовать определённому первой директивой >EQU
.
Например:
>mov eax, count
>count equ 1
>mov eax, count
>count equ 2
>mov eax, count
>count equ 3
>mov eax, count
>restore count
>mov eax, count
>restore count
>mov eax,count
>restore count
>mov eax,count
получим:
>mov eax, count
>mov eax, 1
>mov eax, 2
>mov eax, 3
>mov eax, 2
>mov eax, 1
>mov eax, count
Если попытаться выполнить >RESTORE
большее количество раз, чем было сделано >EQU
, никаких предупреждений выдано не будет. Значение идентификатора будет неопределенно.
Например:
>mov eax, count
>restore count
>mov eax, count
получим:
>mov eax, count
>mov eax, count
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. Поведение макросов
Имя макроса будет заменено его телом не только в том случае, если оно расположено в начале строки. Макрос может находиться в любом месте исходного текста, где допустима мнемоника инструкции (например,