последовательности. Первым объявляется внутренний макрос. Внешний макрос объявляется последним. Все константы, используемые в макросах, должны быть объявлены перед объявлением макросов. Макрос определяется двумя директивами. Первая директива имеет формат:
.MACRO имя_макроса (аргумент1, аргумент2, ...);
Завершает макрос директива окончания макроса:
.ENDMACRO;
Каждый оператор внутри макроса может быть инструкцией, директивой или макровключением. Макрос вызывается по своему имени. Чтобы выполнить макрос с именем mac1, необходимо вставить в текст программы команду mac1;. Макровызов не должен содержать дополнительных операторов в строке вызова (т.е. инструкций, директив препроцессора или других макровключений).
Аргументы макроса имеют форму записи:
%n
, где n = 0, 1, 2, …, 9;
Следующий пример определяет макрос sum с тремя аргументами:
.MACRO sum(%0, %1, %2);
В коде макроса аргументы маркируются служебными символами %1, %2, %3, и т.д. При вызове макроса служебные символы замещаются величинами аргументов, переданных в макрос. При вызове макроса ему должно быть передано правильное число аргументов. Допустимые передаваемые аргументы и исключения для них приведены в табл. 11.4.
Таблица 11.4
Аргумент | Исключение |
---|---|
Константа или арифметическое выражение | Нет |
Символы | MACRO, ENDMACRO, CONST, INCLUDE |
^буфер | ^%n |
%буфер | %%n |
Операторы ^ и % не могут быть использованы с аргументами, замещающими служебные символы в макроопределении. Тем не менее, аргументы, переданные в макрос, могут использовать эти операторы. Например: read_data(^input);
Директива LOCAL задает программные метки, используемые в макросе. Данная директива указывает ассемблеру создавать уникальную версию метки при каждом включении макроса. Это предотвращает ошибку дублирования меток в случае, когда макрос вызывается несколько раз в одном программном модуле. Директива имеет формат записи:
.LOCAL метка1, метка2, ...;
Ассемблер создает уникальные версии меток макроса, добавляя к ним номер. Это можно увидеть в файле листинга с расширением lst. Помните, что для раскрытия макросов в листинге необходимо при запуске программы компилятора asm21 добавить ключ -m.
Ниже приведен простейший пример макроса, позволяющий вставить в любое место программы несколько пустых команд пор.
.MACRO nops;
nop; nop; nop; nop; nop; nop;
.ENDMACRO;
Вызов данного макроса в программе осуществляется командой nops;. Следующий пример показывает, как создать макрос wait с одним параметром и одной локальной меткой.
MACRO wait(%0);
local loop;
cntr=%0;
do loop until ce;
loop: nop;
ENDMACRO;
Этот макрос позволяет организовать в программе функцию задержки на 100 циклов лаконичной записью:
wait(100);
Естественно, что вместо числа 100 можно вписывать любое число в разрешенном диапазоне для счетчика циклов.
Ниже приведен пример макроса, реализующий подпрограмму, которая переносит содержимое буфера данных из одной области памяти в другую.
.MACRO mem_trans (%0, %1, %2, %3, %4) {Использует 5 аргументов}
.LOCAL trans;
I4=%0; {Установить I4 как адрес источника}
I5=%1; {Установить I5 как адрес приемника}
M4=1 {Установить указатель на инкремент 1}
CNTR=%2 {Установить длину буфера}
DO trans UNTIL СЕ; {Перенос данных}
si=%3(I4, M4) {Перенос данных из типа %3 памяти}
trans: %4(I5, M4)=si; {В тип %4 памяти}
.ENDMACRO
Пример вызова этого макроса в программе может быть таким:
mem_trans (^tabl_coef, ^buf, %buf, PM, DM);
Здесь в качестве аргументов в макрос передаются адреса буферов tabl_coef и but, длина буфера but и тип памяти. Заметьте, что зарезервированные ключевые слова PM и DM переданы как аргументы.
Несколько следующих директив определяют формат файла листинга. Файл листинга с расширением lst позволяет представить результаты процесса ассемблирования. Ниже показан пример файла листинга простейшей программы. В этом файле используются следующие информационные поля:
addr — смещение от базового адреса модуля;
inst — код операции;
source line — номер строки исходного файла и код.
Release 5.11 Assembler Version 1.34s 9/19/95
D:TEMAIKSPROGTEST.DSPDOS.dsp Mon Jun 21 17:07:36 2004 Page 1
addr inst source line
1 .module/RAM/ABS=0 example;