Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции / Лекция 8 / Лекция 8.doc
Скачиваний:
24
Добавлен:
10.06.2015
Размер:
223.74 Кб
Скачать

Глава 14

Макросредства языка ассемблера

Понятие о макросредствах языка ассемблера

Псевдооператоры EQU и =

Макрокоманды и макродирективы

Директивы условной компиляции

Директивы генерации ошибок пользователя

Директивы управления листингом

Язык ассемблера не относится к простым языкам программирования. По истечении некоторого времени после начала программирования на ассемблере становятся видны свойственные этому языку проблемы. Перечислим некоторые из них:

-плохая читаемость исходных текстов программы — спустя некоторое время при недостаточном комментировании могут возникнуть проблемы с пониманием особенностей алгоритма, лежащего в основе программы;

-ограниченность набора команд;

-полная или почти полная повторяемость некоторых фрагментов программы;

-необходимость включения в каждую новую программу одних и тех же фрагментов кода и т. д.

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

-расширения набора директив;

-введения некоторых дополнительных команд, не имеющих аналогов в системе команд процессора;

-введения сложных типов данных.

Однако этот перечень исчерпывает все глобальные направления, по которым развивается транслятор от версии к версии. Что же делать программисту для решения его локальной задачи, для адаптации процесса разработки к нуждам определенной проблемной области? Для этого разработчики компиляторов ассемблера включают в язык и постоянно совершенствуют аппарат макросредств. Этот аппарат является очень мощным и важным. В общем случае есть смысл говорить о том, что транслятор ассемблера состоит из двух частей — непосредственно транслятора, формирующего объектный модуль, и макроассемблера. Если вызнакомы с языком С или C++, то, конечно, знаете используемый в нем механизм препроцессорной обработки. Основные принципы его работы аналогичны принципам работы макроассемблера. Для тех, кто ничего раньше не слышал об этом механизме, поясню его суть. Основная идея — использование подстановок, когда определенным образом организованная символьная последовательность заменяется другой символьной последовательностью. Создаваемая последовательность может описывать как данные, так и программные коды. Главное здесь то, что на входе макроассемблера текст программы может быть весьма далеким по виду от ассемблера, но на выходе обязательно будет текст на чистом ассемблере, содержащем символические аналоги машинных команд процессора. Таким образом, обработка программы на ассемблере с использованием макросредств неявно осуществляется транслятором в две фазы. На первой фазе работает часть компилятора, называемая макроассемблером, основные функции которого мы описали ранее.

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

Далее мы обсудим основной набор макросредств компилятора TASM. Отметим, что большинство этих средств доступно и в компиляторе MASM фирмы Microsoft. Обсуждение начнем с простейших средств и закончим более сложными.

Псевдооператоры EQU и =

К простейшим макросредствам языка ассемблера можно отнести псевдооператоры EQL) и = (равно). Их мы уже неоднократно использовали при написании программ. Данные псевдооператоры предназначены для присвоения некоторому выражению символического имени или идентификатора. Впоследствии, когда в ходе трансляции такие идентификаторы встречаются в теле программы, макроассемблер подставляет вместо них соответствующее выражение. Выражениями могут быть константы, имена меток, символические имена и строки в апострофах. После присвоения этим конструкциям символических имен их можно использовать везде, где эти конструкции могли бы присутствовать.

Синтаксис псевдооператора EQU:

имя_идентификатора equ строка или числовое_выражение

Синтаксис псевдооператора =:

имя_идентификатора = числовое_выражение

Несмотря на внешнее и функциональное сходство, псевдооператоры EQU и = различаются следующим:

-с помощью псевдооператора EQU идентификатору можно ставить в соответствие

как числовые выражения, так и текстовые строки, а псевдооператор = может использоваться только с числовыми выражениями;

-идентификаторы, определенные с помощью псевдооператора =, можно переопределять в исходном тексте программы, а определенные с использованием псевдооператора EQU — нельзя.

Ассемблер всегда пытается вычислить значение строки, воспринимая ее как выражение. Для того чтобы строка воспринималась именно как текстовая, необходимо заключить ее в угловые скобки:

<строка>

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

Псевдооператор EQU удобно использовать для настройки программы на конкретные условия выполнения, замены сложных в обозначении объектов, многократно встречающихся в программе, более простыми именами и т. п. К примеру,

masra

model small

stack 256

mas_size equ 10 ;размерность массива

akk equ ax переименовать регистр

mas_elem equ mas[bx][si] адресовать элемент массива

.data

;описание массива из 10 байт:

mas db mas_size dup (0)

. code

mov akk,@data фактически mov ax,@data

mov ds.akk фактически mov ds.ax

mov al,mas_elem фактически mov a l , m a s [ b x ] [ s i ]

Псевдооператор = удобно использовать для определения простых абсолютных (то есть не зависящих от места загрузки программы в память) математических выражений. Главное условие — транслятор должен быть в состоянии вычислять эти выражения во время трансляции. К примеру,

.data

adrl db 5 dup (0)

adr2 dw 0

Ten = 43

len = len+1 ;можно и так, через предыдущее определение

len = adr2-adrl

Как видно из примера, в правой части псевдооператора = можно использовать метки и ссылки на адреса — главное, чтобы в итоге получилось абсолютное выражение.

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

Под строками здесь понимается текст, описанный с помощью псевдооператора EQU.

Эти директивы перечислены далее.

Директива слияния строк CATSTR:

идентификатор catstr строка_1,строка_2,...

Значением этого макроса будет новая строка, состоящая из сцепленной слева направо последовательности строк строка_1, строка_2 и т. д. В качестве сцепляемых строк могут быть указаны имена ранее определенных макросов. К примеру,

рге equ Привет,

name equ < Юля>

privet catstr pre,name ;privet= "Привет, Юля"

Директива выделения подстроки в строке SUBSTR:

идентификатор substr строка,номер_позиции.размер

Значением данного макроса будет часть строки, заданной операндом строка, начинающаяся с позиции с номером номер_позиции и длиной, указанной операндом размер. Если требуется только остаток строки начиная с некоторой позиции, то достаточно указать номер позиции (без размера). К примеру,

;продолжение предыдущего фрагмента:

privet catstr pre,name ;privet= "Привет, Юля"

name substr privet,7,3 ;пагае="Юля"

Директива определения вхождения одной строки в другую INSTR:

идентификатор i n s t r номер_нач_позиции,строка_1,строка_2

После обработки данного макроса транслятором операнду идентификатор будет присвоено числовое значение, соответствующее номеру (первой) позиции, с которой совпадают операнды строка_1 и строка_2. Если такого совпадения нет, то идентификатор получит значение 0.

Директива определения длины строки в текстовом макросе SIZESTR:

идентификатор sizestr строка

В результате обработки данного макроса значение идентификатор устанавливается равным длине строки:

;как продолжение предыдущего фрагмента:

privet catstr pre.name ;privet= "Привет, Юля"

len sizestr privet ;len=10

Эти директивы очень удобно использовать при разработке макрокоманд, которые являются следующим типом макросредств, предоставляемых компилятором ассемблера.

Соседние файлы в папке Лекция 8