Справочник по языку Ассемблера IBM PC



       

Макрокоманды - часть 7


/p>

Эту директиву необходимо размещать непосредственно за заголовком макроопределения.
Результатом работы этой директивы будет генерация в каждом экземпляре макрорасширения уникальных имен для всех идентификаторов, перечисленных в список_идентификаторов. Эти уникальные имена имеют вид ??xxxx, где хххх — шестнадцатеричное число.
Для первого идентификатора в первом экземпляре макрорасширения хххх= 0000, для второго — хххх= 0001 и т. д. Контроль за правильностью размещения и использования этих уникальных имен берет на себя ассемблер.

Для того чтобы вам окончательно все стало понятно, введем и подвергнем трансляции листинг 3. В нем, кроме некоторых ранее рассмотренных макрокоманд, содержится макрокоманда num_char. Ее назначение — подсчитывать количество символов в строке, адрес которой передается этой макрокоманде в качестве фактического параметра. Строка должна удовлетворять требованию, предъявляемому к строке, предназначенной для вывода на экран функцией 09h прерывания 21h, то есть заканчиваться символом $.
Другой момент, который нашел отражение в этой программе, — использование символа $ для распознавания формального аргумента в строке, заключенной в кавычки ' ' (см. последний фрагмент).

Листинг 3. Пример 2 создания и использования макрокоманд

;prg_13_2.asm init_ds macro ;макрос настройки ds на сегмент данных mov ax,data mov ds,ax xor ax,ax endm out_str macro str ;макрос вывода строки на экран. ;На входе — выводимая строка. ;На выходе — сообщение на экране. push ax mov ah,09h mov dx,offset str int 21h pop ax endm exit macro ;макрос конца программы mov ax,4c00h int 21h endm num_char macro message local m1,elem,num,err_mes,find,num_exit ;макрос подсчета количества символов в строке. ;Длина строки — не более 99 символов. ;Вход: message — адрес строки символов, ограниченной '$' ;Выход: в al — количество символов в строке message и вывод сообщения jmp m1 elem db 'Строка &message содержит ' num db 2 dup (0) ;число символов в строке message в коде ASCII db ' символов',10,13,'$' ;конец строки для вывода функцией 09h err_mes db 'Строка &message не содержит символа конца строки',10,13,'$' m1: ;сохраняем используемые в макросе регистры push es push cx push ax push di push ds pop es ;настройка es на ds mov al,'$' ;символ для поиска — `$` cld ;сброс флага df lea di,message ;загрузка в es:di смещения строки message push di ;запомним di — адрес начала строки mov cx,99 ;для префикса repne — максимальная длина строки ;поиск в строке (пока нужный символ и символ в строке не равны) ;выход — при первом совпавшем repne scasb je find ;если символ найден — переход на обработку ;вывод сообщения о том, что символ не найден push ds ;подставляем cs вместо ds для функции 09h (int21h) push cs pop ds out_str err_mes pop ds jmp num_exit ;выход из макроса find: ;совпали ;считаем количество символов в строке: pop ax ;восстановим адрес начала строки sub di,ax ;(di)=(di)-(ax) xchg di,ax ;(di) (ax) sub al,3 ;корректировка на служебные символы — 10, 13, '$' aam ;в al две упакованные BCD-цифры результата подсчета or ax,3030h ;преобразование результата в код ASCII mov cs:num,ah mov cs:num+1,al ;вывести elem на экран push ds ;подставляем cs вместо ds для функции 09h (int21h) push cs pop ds out_str elem pop ds num_exit: push di push ax push cx push es endm

data segment para public 'data' msg_1 db 'Строка_1 для испытания',10,13,'$' msg_2 db 'Строка_2 для второго испытания',10,13,'$' data ends

stk segment stack db 256 dup('?') stk ends

code segment para public 'code' assume cs:code,ds:data,ss:stk main proc init_ds out_str msg_1 num_char msg_1 out_str msg_2 num_char msg_2 exit main endp code ends end main

В теле макроопределения можно размещать комментарии и делать это особым образом.
Если применить для обозначения комментария не одну, как обычно, а две подряд идущие точки с запятой, то при генерации макрорасширения этот комментарий будет исключен.
Если по какой-то причине необходимо присутствие комментария в макрорасширении, то его нужно задавать обычным образом, то есть с помощью одинарной точки с запятой. Например:

mes macro messsage ... ;этот комментарий будет включен в текст листинга ... ;;этот комментарий не будет включен в текст листинга endm




Содержание  Назад  Вперед