Руководство по препроцессору FASM (Неизвестен) - страница 12

>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 `