Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скляров И. Изучаем Assembler за 7 дней (2010).pdf
Скачиваний:
1335
Добавлен:
23.02.2015
Размер:
2.11 Mб
Скачать

http://www.sklyaroff.ru

67

3.9. Макросы

Сейчас мы изучим языковое средство ассемблера MASM, из-за которого он собственно и получил свое название Macro Assembler (макроассемблер).

Макрос (макроопределение) — это символьное имя, заменяемое при ассемблировании на последовательность программных инструкций.

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

Отличие макроса от обычной подпрограммы заключается в том, что, если в исходном тексте будет несколько вызовов макроса, то его тело будет повторено столько же раз. Тело же обычной подпрограммы существует в единственном экземпляре независимо от количества вызовов. Хотя программа, использующая подпрограмму, расходует меньше места, но программа с макросом будет выполняться быстрее, т. к. в ней не будет лишних команд CALL и RET. Кроме того, тело макроса может изменяться в зависимости от тех аргументов, с которыми он вызван, обычная подпрограмма такое свойство обеспечить не может.

Макрос должен быть описан до первого вызова. Описание макроса еще называют макроопределением. Макроопределение начинается директивой MACRO и заканчивается ENDM. Как правило, макроопределения помещаются либо в начале исходного текста программы, либо в отдельный текстовый файл, который включается в исходную программу на этапе трансляции с помощью директивы

INCLUDE.

Синтаксис макроопределения следующий:

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

ENDM

Пример макроопределения без использования аргументов: ah9 MACRO

mov ah,9 int 21h ENDM

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

Пример макроопределения с использованием аргументов: addx MACRO x1,x2,x3

mov x1,x2

;;

add x1,x3

;; сложение

ENDM

 

Макрос addx складывает значения указанные в параметрах x2 и x3 и сохраняет результат в регистре, который должен быть указан в первом параметре x1. К примеру, если в программе с макроопределением вставить строку:

addx ax,20h,-7

то ассемблер заменит ее на следующие две инструкции:

mov ax,20h add ax,-7

http://www.sklyaroff.ru

68

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

3.9.1. Блоки повторений

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

Директивы WHILE и REPT

Данные директивы выполняют повторение участка программы заданное число раз. Синтаксис директивы WHILE:

WHILE константное_выражение инструкции

ENDM

Синтаксис директивы REPT:

REPT константное_выражение инструкции

ENDM

Обе директивы повторяют инструкции столько раз, сколько это определено значением константное_выражение. Отличие директивы REPT от директивы WHILE в том, что она автоматически уменьшает на единицу значение константное_выражение после каждой итерации. В тело директивы WHILE нужно обязательно включать счетчик уменьшения значения константное_выражение, в ином случае цикл будет работать вечно, из-за чего на этапе транслирования ассемблер просто повиснет.

Пример макроса с использованием директивы WHILE: mem0 MACRO ln

len=ln WHILE len db 0 len=len-1 ENDM

ENDM

Если в программе вставить строку:

mem0 100

то будет сгенерировано 100 директив DB 0.

Пример макроса с использованием директивы REPT: mem1 MACRO ln

len=ln

x=0 REPT len db x x=x+1 ENDM

ENDM

http://www.sklyaroff.ru

69

Если в программе вставить строку:

mem1 256

то будет сгенерировано 256 байт данных со значениями от 0 до 256.

Директива IRP

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

IRP параметр,<значение1, значение2 ...> инструкции

ENDM

Блок будет вызываться столько раз, сколько значений указано в списке (в угловых скобках). Обратите внимание угловые скобки (<>), обрамляющие список значений, являются обязательными. Например, выражение:

IRP reg,<ax,bx,cx,dx,si,di> push reg

ENDM

приведет к генерации следующих инструкций: push ax

push bx push cx push dx push si push di

Директива IRPC Синтаксис директивы IRPC:

IRPC параметр,строка инструкции

ENDM

Действие этой директивы подобно IRP, но отличается тем, что на каждой итерации параметр заменяется очередным символом из строки. Следовательно, количество повторений равно количеству символов в строке.

Если строка содержит пробелы, запятые и другие разделительные символы, то она должна заключаться в угловые скобки (<>). Обратите также внимание, в том случае если параметру в блоке повторения непосредственно предшествуют и/или следуют сразу за ним какие-либо символы, то параметр должен обрамляться (экранироваться) с соответствующих сторон символом амперсанда (&). В примере ниже параметр char заключен в одинарные кавычки, поэтому он обрамляется с обеих сторон амперсандами '&char&':

IRPC char,abcd db '&char&',0 ENDM

Данный фрагмент эквивалентен следующей последовательности:

http://www.sklyaroff.ru

70

db 'a',0 db 'b',0 db 'c',0 db 'd',0

Директива EXITM

Директива EXITM (сокращение от exit macro) выполняет немедленный выход из макроопределения или блока повторения.

Директива LOCAL Синтаксис директивы:

LOCAL метка

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

Обычно метки, генерируемые транслятором, имеют следующий формат: ??nnnn, где вместо nnnn подставляется уникальный номер.

Директива PURGE Синтаксис директивы:

PURGE имя_макроса

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