Макропеременные и макровычисления
Макропеременные могут быть только целочисленными. Они создаются на период компиляции с помощью операции = (знак равенства). Значение константы в процессе компиляции можно переопределять сколько угодно раз. Например
MyVar = 10
Это переменные, с которыми работает компилятор ML как любое приложение работает со своими переменными. Компилятор может в процессе трансляции выполнять много вычислительных операций. В том числе можно программировать циклы, проверки условий. Рассмотрим некоторые примеры.
Создание в секции данных описания числового массива из десяти квадратов первых десяти целых чисел.
.data
A=1
Massiv Label Word
Repeat 10
Dw A*A
A = A+1
Endm
Макрогенератор создаст следующее:
.data
A=1
Massiv Label Word
Dw A*A
A = A+1
Dw A*A
A = A+1
Dw A*A
A = A+1
Dw A*A
A = A+1
Dw A*A
A = A+1
Dw A*A
A = A+1
Dw A*A
A = A+1
Dw A*A
A = A+1
Dw A*A
A = A+1
Dw A*A
A = A+1
Все вычисления выполнятся в период трансляции. Здесь же мы наблюдаем работу только макрогенератора, а он, как говорилось выше, манипулирует только текстами.
Пример – записать через цикл операторы сохранения в стек регистров, чьи имена заканчиваются на X:
irpc rg, ABCD
push rg&X
endm
Увидеть работу макрогенератора
Если обработать исходный asm-файл вызовом компилятора ML с ключом /EP, то компилятор собственно трансляцию в машинные коды проводить не станет, выполнится только работа макрогенератора (препроцессора). Изменённый макрогенератором исходник компилятор ML будет выводить на стандартный вывод, т.е. на экран консоли. Читать можно, но неудобно. Мы же вполне можем его перенаправить в файл командой > наш_файл.какое_хотим_расширение. Потом этот файл откроем в редакторе и будем читать. Получится консольная команда вроде такой:
ML /ep myfile.asm > myfile.LST
Здесь выводному файлу мы заказали расширение LST («листинг»). Можно любое, но это всё равно будет текстовый файл.
Расширенный листинг
Существует и другой способ увидеть «развёрнутые» макросы – это создать при компиляции (параллельно с ней) так называемый расширенный листинг программы. Для этого в вызове компилятора следует дополнительно задать ключи /Fl[имя_файла_листинга] /Sa.
Компилятор строит расширенный листинг (назовем его для краткости ELST – “extended listing”) так. Он просматривает исходный текст сверху вниз. Каждая строка исходного текста переносится в ELST «как есть». Если эта строка является макровызовом, то ниже вставляются строки макрорасширения. Они метятся слева числом – уровнем вложенности макрорасширения.
Если строка исходника или вставленная строка макрорасширения является командой, то она компилируется. Что положено - пишется в объектный файл.obj. В ELST откомпилированная строка записывается в формате
Расширенный листинг, в принципе, дает полное представление о результатах работы компилятора. Для более полного представления приведем еще один фрагмент расширенного листинга.
1 2 3
---------┴----------------┴--------------------------
00000000 A1 00000000 R Mov EAX, Num1 ; 11223344
00000005 8A 15 0000001A R Mov dl, [Str2 + 3] ; J
macrodef EAX, EDX, Num1
1 LOCAL M3
0000000B 8B D0 1 mov EDX, EAX;обычная команда
1 ;с обычным комментарием
0000000D 1 ??0019:
0000000D FF 35 00000000 R 1 push Num1
Обратите внимание на колонку 2. Она содержит объектный код, который впоследствии реально попадает в готовую программу. Строчки, в которых колонка 2 пустая, не порождают объктного кода и служат только пользователю для лучшего понимания программы.
3. Порядок выполнения работы: