Инструменты пользователя

Инструменты сайта


examination:asm:question25

Вопрос №25. Понятие макрогенерации. Макроассемблер. Макроопределение (МО), макрокоманда, макрорасширение, макроподстановка. Примеры

МАКРОГЕНЕРАТОР

Возможны два варианта взаимодействия макрогенератора (МГ) с ассемблером. В первом варианте МГ работает до ассемблера и полностью независим от него: МГ вводит текст программы на макроязыке и преобразует его, получая новый текст на «чистом» языке ассемблера (ЯА), и только затем начинает работать ассемблер. В этом случае МГ выступает в роли т.н. препроцессора (препроцессором называют вспомогательную программу, работающую до основной программы и преобразующую исходный текст к виду, удобному для работы основной программы). Достоинством этого варианта является то, что так легче понять сам макроязык и работу МГ, так легче реализовать МГ и ассемблер. Однако у этого варианта имеются недостатки. Во-первых, приходится дважды просматривать текст программы (а это потери времени), а во-вторых, и это главное, при таком взаимодействии МГ не может использовать информацию, извлекаемую ассемблером из программы.

Отмеченные недостатки устраняются при втором варианте взаимодействия МГ с ассемблером - когда текст программы просматривается только раз, но его обрабатывают одновременно (а точнее, чередуясь) и МГ, и ассемблер. Делается это так. Очередное предложение программы сначала просматривает МГ. Если это обычное предложение ЯА (например, директива N EQU 1), тогда МГ ничего с ним не делает, а сразу передает его на обработку ассемблеру. Ассемблер же, обработав это предложение (у нас - записав в таблицу имен, что N - это имя константы со значением 1), возвращает управление МГ, который переходит к следующему предложению программы. Если же очередное предложение программы - это конструкция макроязыка (например, IF N EQ 1), тогда его обработкой занимается сам МГ. В таких случаях МГ либо ничего не сообщает ассемблеру об этом предложении (как в случае директивы IF), либо (если это макрокоманда) генерирует несколько обычных предложений, которые по одному передает на обработку ассемблеру, и только после этого переходит к следующему предложению программы. Ясно, что в данном случае МГ может пользоваться информацией, извлеченной ассемблером из программы; например, в нашем случае МГ может забраться в таблицу имен и узнать, что означает имя N.

Турбоассемблер поддерживает возможности макроязыка. Этот язык, имея некоторый син-таксис, позволяет упрощать написание сложных структурированных программ, при этом исходные конструкции макроязыка не участвуют в процессе трансляции и создании объ-ектного кода. Как правило макрогенератор является составной частью программы-транслятора. Макрогенератор всего лишь производит текстовые замены. Правила тексто-вых замен формулируются внутри макроопределения. Применение правил внутри про-граммы называется применением макрокоманды. Сам процесс текстовой замены в про-грамме по указанным правилам называется макроподстановкой и полученная замена но-сит название макрорасширения. Макроопределение м.б. построено внутри файла-текста программы (в начале) либо в отдельном файле или макробиблиотеке. Для построения макроопределения используется директива macro.

Если вызвать макрокоманду следующим образом: command x=1, то макрогенератор вме-сто этой записи подставит x=1.

command mov ax,1 - mov ax,1

Макрокоманды

Идейно макрокоманда представляет собой дальнейшее развитие механизма замены текста. С помощью макрокоманд в текст программы можно вставлять последовательности строк (которые логически могут быть данными или командами) и даже более того — привязывать их к контексту места вставки.

Представим ситуацию, когда необходимо выполнить некоторые повторяющиеся действия.

<1> ;———Prg_3_1.asm———————————-

<2> ;Программа преобразования двузначного шестнадцатеричного числа <3> ;в символьном виде в двоичное представление. <4> ;Вход: исходное шестнадцатеричное число из двух цифр, <5> ;вводится с клавиатуры. <6> ;Выход: результат преобразования должен <7> ;быть в регистре al.

<8> ;——————————————————

<9> data segment para public 'data' ;сегмент данных

<10> message db 'Введите две шестнадцатеричные цифры,$'

<11> data ends

<12> stk segment stack

<13> db 256 dup ('?') ;сегмент стека

<14> stk ends

<15> code segment para public 'code' ;начало сегмента кода

<16> main proc ;начало процедуры main

<17> assume cs:code,ds:data,ss:stk

<18> mov ax,data ;адрес сегмента данных в регистр ax

<19> mov ds,ax ;ax в ds

<20> mov ah,9

<21> mov dx,offset message

<22> int 21h

<23> xor ax,ax ;очистить регистр ax

<24> mov ah,1h ;1h в регистр ah

<25> int 21h ;генерация прерывания с номером 21h

<26> mov dl,al ;содержимое регистра al в регистр dl

<27> sub dl,30h ;вычитание: (dl)=(dl)-30h

<28> cmp dl,9h ;сравнить (dl) с 9h

<29> jle M1 ;перейти на метку M1 если dl<9h или dl=9h

<30> sub dl,7h ;вычитание: (dl)=(dl)-7h

<31> M1: ;определение метки M1

<32> mov cl,4h ;пересылка 4h в регистр cl

<33> shl dl,cl ;сдвиг содержимого dl на 4 разряда влево

<34> int 21h ;вызов прерывания с номером 21h

<35> sub al,30h ;вычитание: (dl)=(dl)-30h

<36> cmp al,9h ;сравнить (al) с 9h 28

<37> jle M2 ;перейти на метку M2, если al<9h или al=9h

<38> sub al,7h ;вычитание: (al)=(al)-7h

<39> M2: ;определение метки M2

<40> add dl,al ;сложение: (dl)=(dl)+(al)

<41> mov ax,4c00h ;пересылка 4c00h в регистр ax

<42> int 21h ;вызов прерывания с номером 21h

<43> main endp ;конец процедуры main

<44> code ends ;конец сегмента кода

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

имя_макрокоманды macro список_формальных_аргументов

тело макроопределения

endm

Где должны располагаться макроопределения? Есть три варианта:

1.В начале исходного текста программы до сегмента кода и данных с тем, чтобы не ухудшать читабельность программы. Этот вариант следует применять в случаях, если определяемые вами макрокоманды актуальны только в пределах одной этой программы.

2.В отдельном файле. Этот вариант подходит при работе над несколькими программами одной проблемной области. Чтобы сделать доступными эти макроопределения в конкретной программе, необходимо в начале исходного текста этой программы записать директиву include имя_файла, к примеру:

masm

model small

include show.inc

;в это место будет вставлен текст файла show.inc

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

Обычно макрокоманда содержит некоторый список аргументов — список_фактических_аргументов, которыми корректируется макроопределение. Места в теле макроопределения, которые будут замещаться фактическими аргументами из макрокоманды, обозначаются с помощью так называемых формальных аргументов. Таким образом, в результате применения макрокоманды в программе формальные аргументы в макроопределении замещаются соответствующими фактическими аргументами; в этом и заключается учет контекста. Процесс такого замещения называется макрогенерацией, а результатом этого процесса является макрорасширение.

К примеру, рассмотрим самое короткое макроопределение — clear_rg.

clear_r ax

xor ax,ax

Теперь обсудим вопрос — как транслятор распознает формальные аргументы в теле макроопределения для их последующей замены на фактические аргументы?

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

examination/asm/question25.txt · Последние изменения: 2014/01/15 12:12 (внешнее изменение)