>macro declare_macro_AAA
>{
> macro AAA
> {
> db 'AAA',0
> } ;завершаем определение AAA
>} ;завершаем определение declare_macro_AAA
Проблема в том, что когда макрос >declare_macro_AAA
обрабатывается препроцессором, первая найденная скобочка >}
считается завершением определения его, а не так как хотелось бы. Так же происходит и с другими символами и/или операторами (например, >#
, >`
, >forward
, >local
).
Но со временем, была добавлена новая директива. Она работает подобно >EQU
, но обрабатывается до любого другого препроцессинга. (За исключением предварительных операций, про которые говорится в разделе Общие понятия — они выполняются как бы до самого препроцессинга, но это уже внутренние детали, не слишком интересные). Директива эта называется >FIX
:
Синтаксис:
>name1 fix name2
Видно, что синтаксис такой же как у >EQU
, но как я сказал, когда препроцессор обрабатывает часть кода, он смотрит, есть ли >FIX
, а потом уже делает всё остальное. Например код:
>a equ 10
>b fix 10
>mov ax, a
>mov bx, b
будет преобразован в:
>mov ax, 10
>mov bx, 10
Но при обработке такого кода:
>equ fix =
>a equ 10
>mov ax, a
в первой строк директива >FIX
скажет препроцессору поменять все >EQU
на >=
. Далее, перед обработкой следующей строки, препроцессор проверит, нет ли там пофиксеных идентификаторов. Так что в нашей второй строке >equ
будет заменено на >=
, и строка примет вид >a = 10
. Так что никакой другой обработки этой строки не будет выполнено. А значит, и третья строка не будет преобразовываться препроцессором, так как идентификатор a не будет определён директивой >EQU
. Результат всего этого будет такой:
>a = 10
>mov ax, a
Директива >FIX
может быть использован и для определения макросов в макросах — того, что мы хотели сделать в нашем гипотетичном примере. Делается это подобным образом:
>macro declare_macro_AAA
>{
> macro AAA
> %_
> db 'aaa',0
> _%
>}
>%_ fix {
>_% fix }
>declare_macro_AAA
Здесь, препроцессор найдёт объявление макроса >declare_macro_AAA
и определит его, далее будет два >FIX
, и потом использование макроса >declare_macro_AAA
. Так что он преобразует это в:
>macro declare_macro_AAA
>{
> macro AAA
> %_
> db 'aaa',0
> _%
>}
>%_ fix {
>_% fix }
>macro AAA
>%_
> db 'aaa',0
>_%
и теперь уже содержимое нового макроса будет обработано препроцессором. Далее будут заменены аргументы >FIX
ов, и получится:
>macro declare_macro_AAA
>{
> macro AAA
> %_
> db 'aaa',0
> _%
>}
>macro AAA
>{
> db 'aaa',0
>}
как мы и хотели.
Подобным образом можно пофиксить все остальные проблематичные вещи:
>macro declare_macro_TEXT
>{
> macro TEXT [arg]
> %_
> %forward
> db %x arg
> _%
>}
>%_ fix {
>_% fix }
>%forward fix forward
>declare_macro_TEXT
>%x fix `