Irpc sym, prog
DB sym
ENDM
Разумеется, еще проще написать DB'prog'. Пример надуманный.
Но в сочетании с еще одним средством ассемблера — конкатенацией символов — IRPCможет быть полезен. Вернемся к примеру
N1 = 5
N2 = N1+2
N3 = 2*N1-1
N4 = N1 MOD 3
m1 DW N1 DUP(0)
m2 DW N2 DUP(0)
m3 DW N3 DUP(0)
m4 DW N4 DUP(0)
Последние четыре строки можно сгенерировать так:
Irpc k, 1234
m&k DW N&k DUP(0)
ENDM
11.5. Макрокоманды
Мы будем вводить макросы на примере нашей первой программы first.asm. Вот ее текст.
.MODEL small
.STACK 100h
.DATA
msg DB "Hello!",0Dh,0Ah,'$'
.CODE
start: mov ax,@data
mov ds,ax
mov dx,OFFSET msg
mov ah,09h
int 21h
mov ah,4Ch
int 21h
END start
При выполнении упражнений вы будете изменять текст программы.
Макросы позволяют как бы расширить язык машинных команд. Определение макрокоманды имеет вид:
имя MACRO формальные_параметры
<тело макрокоманды>
ENDM
Обратите внимание, что перед директивой ENDMимя макроса не указывается.
Вызов макрокоманды имеет вид
имя фактические_параметры
Вызов макрокоманды Ассемблер заменяет ее телом, подставляя вместо формальных параметров фактические.
Пример. Макрос для вывода строки на экран:
message MACRO string
mov dx, OFFSET string
mov ah, 09h
int 21h
ENDM
Теперь для вывода строки msg достаточно поместить в начале файла first.asm это определение, а в секции кода — message msg. При развертывании макроса вместо этого вызова Ассемблер разместит три строки, составляющие тело макрокоманды, а формальный параметр string заменит фактическим параметром msg.
Упражнение. Что произойдет при трансляции, если заменитьENDMнаmessageENDM? Если закомментировать строкуENDM?
Можно ввести макрооопределение:
DOS MACRO func
mov ah,func
int 21h
ENDM
Тогда предыдущее макроопределение можно переписать так:
message MACRO string
mov dx, OFFSET string
DOS 09h
ENDM
Такие макросы называются вложенными.
Упражнение. Посмотрите, как в листинге отображается вложенность макросов.
Пример. Макрос для помещения в стек регистров из списка
push_regs MACRO reg_list
IRP reg, <reg_list>
push reg
ENDM
ENDM
Обращение к такой макрокоманде имеет вид:
push_regs <ax,cx,si,di>
Здесь угловые скобки обязательны. Если их опустить, то получится, что у макроса четыре аргумента, а их всего один — список регистров, воспринимаемый как единое целое.
Как уже говорилось, в программе для TASMвводить такой макрос не имеет смысла.
Сложнее реализуется макрокоманда для завершения работы программы. Напрашивается решение:
exit MACRO return_code
mov al,return_code
DOS 4Ch
ENDM
Но, как правило, мы заканчиваем программу с нулевым кодом завершения, и хотелось бы писать макровызов exit, а неexit 0. Перепишем макроопределение с использованием условного оператора
exit MACRO ret_code
IFNB <ret_code>
mov al, ret_code
ELSE
mov al,0
ENDIF
DOS 4Ch
ENDM
Оператор IFNB— IF Not Blank — указывает начало условно ассемблируемого блока, включаемого, если параметрret_codeне пустой. Для указания конца условно ассемблируемого блока используется директиваENDIF. Альтернативный код в условно ассемблируемом блоке начинается послеELSE. Параметр<ret_code> заключен в угловые скобки, т.к. должен здесь восприниматося как текстовая строка, а не как выражение, вычисляемое на этапе ассемблирования.
11.6. Включаемые файлы
Чтобы не помещать накопленные нами полезные макроопределения в начале каждого программного файла, поместим их в отдельный файл макроопределений.
файл macro.inc
CRLFT EQU 0Dh,0Ah,'$'
DOS MACRO fun
mov ah,fun
int 21h
ENDM
message MACRO string
mov dx, OFFSET string
DOS 09h
ENDM
exit MACRO return_code
IFNB <return_code>
mov al,return_code
ELSE
mov al,0
ENDIF
DOS 4Ch
ENDM
Окончательно программа first.asm принимает вид.
