assembler. Учебник для вузов_Юров В.И_2003 -637с (862834), страница 66
Текст из файла (страница 66)
Обсуждение начнем с простейших средств и закончим более сложными.Псевдооператоры EQU и =К простейшим макросредствам языка ассемблера можно отнести псевдооператоры EQL) и = (равно). Их мы уже неоднократно использовали при написании программ. Данные псевдооператоры предназначены для присвоения некоторому выражению символического имени или идентификатора. Впоследствии, когда в ходетрансляции такие идентификаторы встречаются в теле программы, макроассемблер подставляет вместо них соответствующее выражение.
Выражениями могут бытьконстанты, имена меток, символические имена и строки в апострофах. После присвоения этим конструкциям символических имен их можно использовать везде,где эти конструкции могли бы присутствовать.Синтаксис псевдооператора EQU:имя_идентификатора equ строка или числовое_выражениеСинтаксис псевдооператора =:имя_идентификатора = числовое_выражениеНесмотря на внешнее и функциональное сходство, псевдооператоры EQU и =различаются следующим:Ш с помощью псевдооператора EQU идентификатору можно ставить в соответствиекак числовые выражения, так и текстовые строки, а псевдооператор = можетиспользоваться только с числовыми выражениями;Ж идентификаторы, определенные с помощью псевдооператора =, можно переопределять в исходном тексте программы, а определенные с использованием псевдооператора EQU — нельзя.Ассемблер всегда пытается вычислить значение строки, воспринимая ее каквыражение.
Для того чтобы строка воспринималась именно как текстовая, необходимо заключить ее в угловые скобки:<строка>Угловые скобки являются оператором ассемблера, называемым оператором выделения. С его помощью транслятору сообщается, что заключенная в угловыескобки строка должна трактоваться как текст, даже если в нее входят служебныеслова ассемблера или операторы.Псевдооператор EQU удобно использовать для настройки программы на конкретные условия выполнения, замены сложных в обозначении объектов, многократно встречающихся в программе, более простыми именами и т.
п. К примеру,masramodelstacksmall256296Глава 14. Макросредства языка ассемблераmas_sizeequ 10;размерность массиваakk equ axпереименовать регистрmas_elemequ m a s [ b x ] [ s i ] адресовать элемент массива.data;описание массива из 10 байт:mas db mas_size dup (0). codemov akk,@dataфактически mov ax,@datamov ds.akkфактически mov d s . a xmov a l , m a s _ e l e mфактически mov a l , m a s [ b x ] [ s i ]Псевдооператор = удобно использовать для определения простых абсолютных(то есть не зависящих от места загрузки программы в память) математическихвыражений. Главное условие — транслятор должен быть в состоянии вычислятьэти выражения во время трансляции.
К примеру,.dataadrldb 5 dup (0)adr2dw 0Ten = 43len = len+1;можно и так, через предыдущее определениеlen = adr2-adrlКак видно из примера, в правой части псевдооператора = можно использоватьметки и ссылки на адреса — главное, чтобы в итоге получилось абсолютное выражение.Компилятор TASM, начиная с версии 3.00, содержит директивы, значительнорасширяющие его возможности по работе с текстовыми макросами. Эти директивы аналогичны некоторым функциям обработки строк в языках высокого уровня.Под строками здесь понимается текст, описанный с помощью псевдооператора EQU.Эти директивы перечислены далее.» Директива слияния строк CATSTR:идентификатор catstr строка_1,строка_2,...Значением этого макроса будет новая строка, состоящая из сцепленной слеванаправо последовательности строк строка_1, строка_2 и т. д.
В качестве сцепляемых строк могут быть указаны имена ранее определенных макросов. К примеру,рге equ Привет,nameequ < Юля>privetcatstrpre,name;privet= "Привет, Юля"» Директива выделения подстроки в строке SUBSTR:идентификатор substr строка,номер_позиции.размерЗначением данного макроса будет часть строки, заданной операндом строка,начинающаяся с позиции с номером номер_позиции и длиной, указанной операндом размер. Если требуется только остаток строки начиная с некоторой позиции, то достаточно указать номер позиции (без размера). К примеру,продолжение предыдущего фрагмента:privet catstrpre,name;privet= "Привет, Юля"namesubstrprivet,7,3;пагае="Юля"i' Директива определения вхождения одной строки в другую INSTR:и д е н т и ф и к а т о р i n s t r номер_нач_позиции,строка_1,строка_2После обработки данного макроса транслятором операнду идентификатор будетприсвоено числовое значение, соответствующее номеру (первой) позиции,Макрокоманды297с которой совпадают операнды строка_1 и строка_2.
Если такого совпадения нет,то идентификатор получит значение 0.Я Директива определения длины строки в текстовом макросе SIZESTR:идентификатор sizestr строкаВ результате обработки данного макроса значение идентификатор устанавливается равным длине строки:;как продолжение предыдущего фрагмента:privet catstrpre.name;privet= "Привет, Юля"lensizestr privet;len=10Эти директивы очень удобно использовать при разработке макрокоманд, которые являются следующим типом макросредств, предоставляемых компиляторомассемблера.МакрокомандыПо смыслу макрокоманда представляет собой дальнейшее развитие механизмазамены текста.
С помощью макрокоманд в текст программы можно вставлять последовательности строк (которые логически могут быть данными или командами)и даже более того — привязывать их к контексту места вставки.Представим ситуацию, когда необходимо выполнить некоторые повторяющиеся действия. Механизм макрокоманд предоставляет возможность заменить одинаковые участки кода одной строкой, а первоначальный исходный текст описатьодин раз в определенном месте программы или во внешнем файле. Дальнейшеенаше обсуждение будет посвящено тому, как это сделать.Определимся с терминологией. Осмысленное рассмотрение данного механизма предполагает понимание смысла терминов макрокоманда и макроопределение.Макрокоманда представляет собой строку, одним из компонентов которой является символическое имя макрокоманды.
Имя макрокоманды может сопровождаться параметрами. Если данная строка встречается в теле исходного текста программы, то транслятор замещает ее одной или несколькими другими строками. Какимиименно строками — определяется макроопределением, которое представляет собойшаблон (описание) макрокоманды.Таким образом, для использования макрокоманды в программе первым деломзадают ее макроопределение.
Синтаксис макроопределения следующий:имя_макрокоманды macro список_формальных_аргументовтело макроопределенияendmГде должны располагаться макроопределения? Есть три варианта.и Макроопределения могут располагаться в начале исходного текста программыдо сегмента кода и данных с тем, чтобы не ухудшать читабельность программы.Этот вариант следует применять в случаях, если определяемые вами макрокоманды актуальны только в пределах одной этой программы.* Макроопределения могут располагаться в отдельном файле. Этот вариант подходит при работе над несколькими программами одной проблемной области.Чтобы сделать доступными эти макроопределения в конкретной программе,Глава 14. Макросредства языка ассемблера298необходимо в начале исходного текста этой программы записать директивуinclude имя_файла, к примеру:masmmodelsmalli nclude show.
inc;в это место будет вставлен текст файла show. inc^ Макроопределения могут располагаться в макробиблиотеке. Если у вас естьуниверсальные макрокоманды, которые используются практически во всех ваших программах, то их целесообразно записать в так называемую макробиблиотеку. Сделать актуальными макрокоманды из этой библиотеки можно с помощью все той же директивы INCLUDE. Недостаток этого и предыдущего способов —в том, что в исходный текст программы включаются абсолютно все макроопределения. Для исправления ситуации можно задействовать директиву PURGE,в качестве операндов которой через запятую перечисляются имена макрокоманд, которые не должны включаться в текст программы.
К примеру,include iomac . i ncpurgeoutstr.exitВ данном случае в исходный текст программы перед началом компиляции транслятор TASM вместо строки include iomac.inc вставит строки из файла iomac.inc,отличающиеся от оригинала тем, что в этих строках будут отсутствовать макроопределения OUTSTR и EXIT.А теперь вернемся к главе б и вспомним программу из листинга 6.1. Проанализируем ее текст, выявим повторяющиеся участки и составим для них макроопределения (листинг 14.1).Листинг 14.1.
Первый пример создания и использования макрокоманд<1><2><3><4><5><6><7><8><9><10><11><12><13><14><15><16><18.><19><20><21><22><23><24><25>;prg_6_l. asm с макроопределениямиinit_ds macro;Макрос настройки ds на сегмент данныхmov a x , datamov d s . a xendmout_str macrostr;Макрос вывода строки на экран.;На входе - выводимая строка.;На выходе - сообщение на экране.push axmov ah,09hmov dx, offset strint 21hpop axendmclear_r macrorg;очистка регистра rgxor rg,rgendmget_char macro;ввод символа;введенный символ в al.Макрокоманды299<26>mov ah.lh<27>int 21h<28>endm<29><30>conv_16_2macro<31>;макрос преобразования символа шестнадцатеричной цифры<32>;в ее двоичный эквивалент в al<33>sub al,30h<34>cmp al,9h<35>jle $+4<36>sub al,7h<37>endm<38><39>exit macro<40>;макрос конца программы<41>mov ax,4c00h<42>int 21h<43>endm<44><45>datasegment para public "data"<46>message db "Введите две шестнадцатеричные цифры (буквыA,B,C,D,E,F - прописные): $"<47>dataends<48>stk segment stack<49>db 256 dup("?")<50>stk ends<51><52>codesegment para public "code"<53>assume cs:code,ds:data,ss:stk<54>mainproc<55>i n i t_d s<56>out_str message<57>clear_r ax<58>get_char<59>conv_16_2<60>mov dl.al<61>mov cl,4h<62>shl dl.cl<63>get_char<64>conv_16_2<65>add dl.al<66><67>xchgdl.alexitрезультат в al<68>main endp<69>code ends<70>end m a i nВ листинге 14.1 в строках 2-7, 8-16,18-21, 23-28, 30-37, 39-43 описаны макроопределения.