assembler. Учебник для вузов_Юров В.И_2003 -637с (862834), страница 68
Текст из файла (страница 68)
Другой момент, которыйнашел отражение в этой программе, — использование символа & для распознавания формального аргумента в строке, заключенной в кавычки " " (см. последнийфрагмент).Листинг 14.2. Второй пример создания и использования макрокоманд;prg_14_2.asminit_ds macro;макрос настройки ds на сегмент данныхmov a x , d a t amov ds.axxor a x , a xendmout_str macrostr;макрос вывода строки на экран.;На входе - выводимая строка.;На выходе - сообщение на экране.push axmov ah,09hmov d x , o f f s e t strint 21hpop axendmexitmacro;макрос конца программыmov ax,4c00hint 21hendmnum_charmacro messagelocalml,elem,num,err_mes,find,num_exit;макрос подсчета количества симвопов в строке.;Длина строки - не более 99 символов.;Вход: message - адрес строки символов, ограниченной "$";Выход: в al - количество символов в строке message;и вывод сообщенияelemjmp mldb"Строка &message содержит "продолжение •&304Глава 14.
Макросредства языка ассемблераЛистинг 14.2(продолжение)nura db 2 dup (0);число символов в строке;message в коде ASCIIdb " символов",10,13,'$';конец строки;для вывода функцией 09herr_mes db "Строка &message не содержит символа конца строки",10,13,'$'ml:/сохраняем используемые в макросе регистрыpush espush expush axpush dipush dspop es;настройка es на dsmov al,'$';символ для поиска - "$"eld;сброс флага dflea di.message;загрузка в es:di смещения;строки messagepushdi;запомним di - адрес начала строкиmov ex,99;для префикса repne - максимальная;длина строки;поиск в строке (пока нужный символ;и символ в строке не равны);выход - при первом совпавшемrepne scasbje find;еспи символ найден - переход на обработку;вывод сообщения о том, что символ не найденpush dsподставляем cs вместо ds для функции 09h (int21h)push cspop dsout_str err_mespop dsjmp num_exit;выход из макросаfind:;совпали;считаем количество символов в строке:pop axвосстановим адрес начала строкиsub di,ах;(di)=(di)-(ах)xchg di ,ax; (di) < > (ax)sub al,3корректировка на служебные;символы - 10, 13, "$"aam;в al две упакованные BCD-цифрырезультата подсчетаor ax 3030hпреобразование результата в код ASCIImov cs num.ahmov cs num+l,al;вывести elem на экранpush ds•.подставляем cs вместо ds для функции 09h (int21h)push cspop dsout_str elempop dsnum_exi t:push dipush axpush expush esendmdatasegment para public "data"msg_l db "Строка_1 для испытания",10,13,'$'msg_2 db "Строка_2 для второго испытания",10,13,'$'dataendsstk segment stackМакродирективы305db 256 dup("?")stk endscodesegment para public "code"assume cs:code,ds:data,ss:stkmainproc1nit_dsout_str msg_lnum_charmsg_lout_strmsg_2num_charmsg_2exitmainendpcodeendsend mainВ теле макроопределения можно размещать комментарии, и делать это особымобразом.
Если применить для обозначения комментария не один, как обычно, а двапоследовательных символа точки с запятой (;;), то при генерации макрорасширения этот комментарий будет исключен. Если по какой-то причине необходимоприсутствие комментария в макрорасширении, то его нужно задавать обычнымобразом, то есть с помощью одного символа точки с запятой, например:mes macromesssage... ;этот комментарий будет включен в текст листинга... ;;этот комментарий не будет включен в текст листингаendmМакродирективыС помощью макросредств ассемблера можно не только частично изменять входящие в макроопределение строки, но и модифицировать сам набор этих строк и дажепорядок их следования. Сделать это можно с помощью набора макродиректив (далее — просто директив).
Их можно разделить на две группы.Ш Директивы повторения WHILE, REPT, IRP и IRPC предназначены для создания макросов, содержащих несколько идущих подряд одинаковых последовательностейстрок. При этом возможна частичная модификация этих строк.я Директивы управления процессом генерации макрорасширений EXITM и GOTO предназначены для управления процессом формирования макрорасширения из набора строк соответствующего макроопределения. С помощью этих директивможно как исключать отдельные строки из макрорасширения, так и вовсе прекращать процесс генерации.
Директивы EXITM и GOTO обычно используютсявместе с условными директивами компиляции, поэтому они будут рассмотрены вместе с ними.Директивы WHILE и REPTДирективы WHILE и REPT применяются для повторения определенное количество разнекоторой последовательности строк. Эти директивы имеют следующий синтаксис:WHILE константное_выражениепоследовательность^трокENDMREPT константное_выражениепоследовательность строкENDM306Глава 14.
Макросредства языка ассемблераОбратите внимание на то, что последовательность повторяемых строк в обеихдирективах ограничена директивой ENDM.При использовании директивы WHILE макрогенератор транслятора будетповторять последовательность строк до тех пор, пока значение константное_выражение не станет равным нулю. Это значение вычисляется каждый раз перед очередной итерацией цикла повторения (то есть значение константное_выражение в процессе макрогенерации должно подвергаться изменению внутри последовательностистрок).Директива REPT, подобно директиве WHILE, повторяет последовательность строкстолько раз, сколько это определено значением константное_выражение.
Отличиеэтой директивы от WHILE состоит в том, что она автоматически уменьшает на единицу значение константное_выражение после каждой итерации. В качестве примера рассмотрим листинг 14.3. В нем демонстрируется применение директив WHILEи REPT для резервирования области памяти в сегменте данных. Имя идентификатора и длина области задаются в качестве параметров соответствующих макросовdef_sto_l и def_sto_2. Заметьте, что счетчик повторений в директиве REPT уменьшается автоматически после каждой итерации цикла. Проанализируйте результаттрансляции листинга 14.3.Листинг 14.3. Использование директив повторения:prg_14_3.asmdef_sto_l macroid_table,ln:=<5>;макрос резервирования памяти длиной ten-.Используется WHILEid_tablelabelbytelen=lnwhilelendb 0len=len-lendraendmdef_sto_2macroid_table,len;макрос резервирования памяти длиной len;Используется REPTid_tablelabelbytereptlendb 0endmendmdatasegment para public 'data'def_sto_l tab_l,10def_sto_2 tab_2,10dataendsinit_ds macro;Макрос настройки ds на сегмент данныхmov ax,datamov ds.axendmexitmacro;макрос конца программыmov ax,4c00hint21hendmcodesegment para public "code"assume cs:code,ds:datamainprocМакродирективы307init_dsexitmainendpcodeendsend mainТаким образом, директивы REPT и WHILE удобно применять для «размножения»в тексте программы последовательности одинаковых строк без внесения в эти строки каких-либо изменений на этапе трансляции.
В частности, эти директивы можно использовать при построении элементов списочных структур [8]. Следующиедве директивы, IRP и IRPC, делают процесс «размножения» более гибким, позволяямодифицировать на каждой итерации некоторые элементы последовательностистрок.Директива IRPДиректива IRP имеет следующий синтаксис:IRP формальный_аргумент,<строка_символов_1последовательность^трокENDMстрока_символов_п>Действие данной директивы заключается в том, что она повторяет последовательность строк п раз, то есть столько раз, сколько строк символов заключено в угловые скобки во втором операнде директивы IRP.
Но это еще не все. Повторениепоследовательности строк сопровождается заменой в этих строках формальногоаргумента очерёдной строкой символов из второго операнда. Так, при первой генерации последовательности строк формальный аргумент в них заменяется первой строкой символов (то есть аргументом строка_символов_1). Если есть втораястрока символов (строка_символов_2), это приводит к генерации второй копии последовательности строк, в которой формальный аргумент заменяется второй строкой символов. Эти действия продолжаются до последней строки символов(строка_символов_п) включительно.К примеру, рассмотрим результат определения в программе такой конструкции:irp i n i , < 1 , 2 .
3 , 4 , 5 >db iniendmМакрогенератором будет сгенерировано следующее макрорасширение:dbdbdbdbdb12345Директива IRPCДиректива IRPC имеет следующий синтаксис:IRPC формальный_аргумент,строка_символовпоследовательность строкENDMДействие данной директивы подобно действию директивы IRP, но отличаетсятем, что она на каждой очередной итерации заменяет формальный аргумент очередным символом из строки символов. Понятно, что количество повторений308Глава 14. Макросредства языка ассемблерапоследовательности строк будет определяться количеством символов в строке символов.
К примеру,irpcpushendmrg.abcdrg&xВ процессе макрогенерации эта директива развернется в следующую последовательность строк:pushpushpushpushaxbxexdxЕсли строка символов, задаваемая в директиве IRP, содержит спецсимволы вродеточек и запятых, то она должна быть заключена в угловые скобки: <ab,,cd>.Директивы условной компиляцииПоследний тип макросредств — директивы условной компиляции. Существует двавида этих директив:Ш директивы компиляции по условию позволяют проанализировать определенныеусловия в ходе генерации макрорасширения и при необходимости изменитьэтот процесс;I» директивы генерации ошибок по условию контролируют ход генерации макрорасширения с целью генерации или обнаружения определенных ситуаций, которые могут интерпретироваться как ошибочные.С этими директивами применяются упомянутые ранее директивы управленияпроцессом генерации макрорасширений EXITM и GOTO.Директива EXITM не имеет операндов, она немедленно прекращает процесс генерации макрорасширения, как только встречается в макроопределении.