Аргументы макроса имеют форму записи:
%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 задает программные метки, используемые в макросе. Данная директива указывает ассемблеру создавать уникальную версию метки при каждом включении макроса. Это предотвращает ошибку дублирования меток в случае, когда макрос вызывается несколько раз в одном программном модуле. Директива имеет формат записи:
.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:\TEMA\IKS\PROG\TEST.DSP\DOS.dsp Mon Jun 21 17:07:36 2004 Page 1
addr inst source line
1 .module/RAM/ABS=0 example;
2 .PAGEWIDTH 70;
3 {Описание переменных}
4 .var/dm flag;
5
6 {Инициализация переменных}
7 .init flag: 0x000f;
8
9 again:
0000 02010F 10 toggle FL1; /* Инвертировать флаг */
0001 18000Fu 11 jump again; /* Зациклить */
12 .endmod;
Каждая строка в листинге этой программы имеет свой номер. При обнаружении ошибки в какой-либо строке программы компилятор выдает именно этот номер строки. Символ «u» в поле inst показывает, что код операции содержит адрес перехода.
Существует пять директив ассемблера для формирования выходного файла листинга.
Директива NEWPAGE
Директива NEWPAGE вставляет разделители страниц. После такой директивы листинг программы продолжится с новой страницы. Данная директива, как и последующие, применяется для выделения программных фрагментов и оформления листинга программы. Пример ее использования:
Читать дальше