5.2. Макросы с несколькими аргументами
У макросов может быть несколько аргументов, разделённых запятыми,
>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
Возможно, появится необходимость объявить метку внутри тела макроса:
>macro pushstr string
>{
> call behind ; помещаем в стек адрес string и переходим к behind
> db string, 0
>behind:
>}
но если использовать такой макрос 2 раза, то и метка >behind
будет объявлена дважды, что приведёт к ошибке. Эта проблема решается объявлением локальной метки >behind
. Это и делает директива >LOCAL
.
Синтаксис:
>local label_name
Директива должна применяться внутри тела макроса. Все метки label_name внутри макроса становятся локальными. Так что, если макрос используется дважды никаких проблем не появляется:
>macro pushstr string
>{
> local behind
> call behind
> db string,0
> behind:
>}
>pushstr 'aaaaa'
>pushstr 'bbbbbbbb'
>call something
На самом деле, behind заменяется на >behind?XXXXXXXX
, где >XXXXXXXX
— какой-то шестнадцатеричный номер генерируемый препроцессором. Последний пример может быть преобразован к чему-то вроде:
> call behind?00000001
> db 'aaaaa', 0
>behind?00000001:
> call behind?00000002
> db 'bbbbbbbb', 0
>behind?00000002:
> call something
Заметьте, Вы не сможете напрямую обратиться к метке содержащей >?
так как это специальный символ в FASM, поэтому он и используется в локальных метках. К примеру, >aa?bb
рассматривается как идентификатор >aa
, специальный символ >?
и идентификатор >bb
.
Если Вам нужно несколько локальных меток — не проблема, их можно указать в одной директиве