Приложение 3. Директивы и команды макроассемблера.

Как много, однако, существует такого, в чем я не нуждаюсь.

Сократ.

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

Директивы SEGMENT - ENDS.

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

имя SEGMENT   [счетный т.][атрибут][комбинированный т.][размер]['класс']

имя ENDS

Счетный тип - BYTE, WORD, PARA(166anr), PAGE (256 байт). Определяет тип выравнивания сегмента.

Атрибут - может иметь значение READONLY. Если какая-либо команда модифи­цирует такой сегмент, то при ассемблировании будет сгенерирована ошибка.

Комбиниротнньпй тип:

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

stack - конкатенация всех сегментов с одинаковым именем в один, на его начало будет указывать SS, SP - на конец сегмента.

common - соединение всех сегментов, имеющих одно имя, в один сегмент, размер которого будет равен наибольшему. Поскольку сегменты будут перекрываться, то и содержимое сегментов будет перекрываться также.

memory - совпадает с common.

at адрес - создание сегмента-шаблона относительно заданного адреса. Размер: USE16- 16-битный сегмент, USE32 - 32-битный сегмент, FLAT- модель, когда вся память состоит из одного сегмента.

Тип класса: сегменты с одинаковым именем класса загружаются один за другим.

Директива GROUP.

Данная директива собирает однотипные сегменты так, чтобы адресация в них была единой.

имя GROUP имя 1 ,имя2,...

Ниже представлена простая программа, где используется директива GROUP. Не­смотря на то, что она состоит из двух сегментов, ее ЕХЕ-модуль может быть преобра­зован

GR GROUP CODE,DAT1 CODE   SEGMENT BYTE

ASSUME CS:CODE

ORG 10OH

BEGIN:

MOV DX,OFFSET GR:STRING

MOV AH, 9

INT 21H RET

CODE ENDS

DAT1   SEGMENT BYTE

STRING DB   'Проверка.',13,10, '$'

DAT1 ENDS

END BEGIN

Директива INCLUDE.

Директива имеет формат: INCLUDE имя_файла. Посредством нее в данном месте программы подключается ассемблерный текст из другого файла. Посредством этой ди­рективы можно собирать программу из нескольких отдельных текстов, что несколько облегчает разработку больших программ. Директива INCLUDE допускает вложение.

Директивы LENGTH, SIZE, TYPE.

LENGTH - возвращает число элементов, определенных операндом DUP: DW 64 DUP (?), DD 10DUP(O) и т.п.

TYPE - возвращает число байт, соответствующих определению указанной пере­менной.

SIZE=TYPE*LENGTH.

Директива NAME.

Способ назначения имени модулю. Действует следующее правило:

1. Если директива NAME присутствует, то ее операнд становится именем модуля.

2. Если директива NAME отсутствует, то именем модуля становятся 6 первых сим­волов в директиве TITLE.

3. Если директивы NAME и TITLE отсутствуют, то именем модуля становится

имя файла.

Выбранное имя передается ассемблером в компоновщик.

Директива LABEL.

Директива позволяет переопределять атрибут определенного имени. Например:

LOO LABEL BYTE

NADW1234H

LOO указывает на первый байт переменной NA.

Директива RECORD.

Предназначена для определения двоичного набора в байте или слове. Формат директивы: имя RECORD имя_поля:ширина[=выражение][,..]. Например:

BIT RECORD ВЕЗ,В2:10,ВЗ:3 -определяет запись, состоящую из трех полей. BIT 1 RECORD BIЕ10=1010110011 В,ВЕ2:6= 111001В -определяет запись с иници­ализацией.

Для того чтобы отвести память под определенные записи далее в тексте програм­мы по данному шаблону должно быть зарезервировано место для данных полей. Заре­зервированному слову или байту присваивается имя: DEFB BIT1 <>. Причем в квад­ратных скобках могут быть переопределены или вновь определены поля. Далее в тек­сте программы переменная DEFB может быть использована в командах типа MOV BX,DEFB.

С директивой RECORD работают также директивы WIDTH и MASK. Директива WIDTH определяет длину в битах поля записи или всей записи: MOVAL.WIDTH BI2 - засылает в FL число 6. Директива MASK возвращает маску из единичных битовых значений, которые определяют битовые позиции, занимаемые данным полем. Ниже показано соответствие полей и масок к ним:

81 1110000000000000

82 0001111111111000

83 0000000000000111

Наконец, имена полей также могут быть использованы в командах типа: MOV AL,BIE При этом в AL будет загружено число, на которое нужно сдвинуть ВП, для того чтобы выровнять поле по правому краю. К примеру, команда MOVCL,B 1 загру­зит в CL число 13, а команда MOVCL,B3 - число 0.

Макроопределение состоит из заголовка: имя MACRO параметры, тела макроса и конца определения ENDM. Ниже приводятся два примера макроопределений.

; макроопределение вывод строки

;вызов: OUT_STRING ST ,  где ST указывает на строку OUT STRING  MACRO STRING

MOV DX, OFFSET STRING

MOV AH, 9

NT 21H

ENDM

/макроопределение установка курсора ;вызов:  LOCATE 12,20 LOCATE   MACRO X,Y

MOV BH,0

MOV AH,2

MOV DH,Y

MOV DL,X INT 10H

ENDM

Макроопределения представляютсобой шаблоны, которые вставляются в программу в томместе,гдеонивызываются.Использованиемакроопределенийвместопроцедурможет увеличить быстродействие программы, но увеличивает ее объем. Макроопределение может быгьвнутридругогомакроопределения,т.е.допускаетсявложенностьмакроопределений.

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

1. Часть макроопределений может не использоваться программой, но во время трансляции они будут загружаться в память и может появиться сообщение о нехватке памяти. Это устраняется директивой PURGE, при наличии которой макроопределения, указанные в ней, удаляются из текста. Формат использова­ния этой директивы имеет вид: PURGE

2. При написании макроопределения может возникнуть потребность перехода на метку. Поскольку макроопределение может вызываться несколько раз, то обыч­ная метка не годится. В пределах, однако, данного макроопределения можно ввести локальные метки при помощи директивы LOCAL.

3. Поскольку мы рассматриваем двухпроходной ассемблер, то возникает потреб­ность избежать ситуации, когда файл, указанный в INCLUDE, будет загружать­ся два раза, используя память и дважды появляясь в листинге. Эта проблема устраняется использованием конструкции:

IF1

INCLUDE имя_файла

ENDIF

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

IFXX условие ELSE

ЬгШ1Р Ниже мы перечисляем их:

№ выражение - если выражение равно нулю, то ассемблер обрабатывает выраже­ние в условном блоке.

ШЕ выражение - если выражение не равно нулю, то ассемблер обрабатывает выра­жение в условном блоке.

1Е1 - если осуществляется первый проход, то обрабатывается выражение в услов­ном блоке.

1Е2 - если осуществляется второй проход, то ассемблер обрабатывает выражение в условном блоке.

ШЫОЕЕидентификатор - если идентификатор не определен в программен не объяв­лен как ЕХТКлЧ то ассемблер обрабатывает операторы в условном блоке.

ШВ <аргумент> - если аргумент пустой символ, то ассемблер обрабатывает опера­торы в условном блоке. Аргумент должен быть в угловых скобках.

предыдущему.

ТЕТОК <АК.01 >, <АК"£т2> - если строка первого аргумента идентична строке вто­рого аргумента, то ассемблер обрабатывает операторы в условном блоке.

предыдущему.

Директивы повторения.

К\ЕРТ выражение - осуществляет повторение блока операторов до директивы ЕИБМ в соответствии с выражением.

1К.РК,<аргументы> - в угловых скобках содержится любое число правильных сим­волов, строк, чисел. Использование директивы иллюстрирует следующий пример:

1ЫР Ы,<2,33,67,33,77>

БВ N

ЕЫОМ

Ассемблером будет сгенерирована последовательность: БВ 2, БВ 33, БВ 67, БВ 33, БВ 77.

ШРС И, строка - ассемблер генерирует блок кода для каждого символа в строке.

Директива выхода ЕХЕШ.

Используется в макроопределениях. Формат использования:

IFXX

EXITM

ENDIF

Как только ассемблер доходит до директивы ЕХ1ТМ, то переходит к командам за ЕИБМ.

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

.1Г усл.

ELSE

.ENDIF

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

стр ах,О

jnz _по add ax,bx

__no:

может быть представлен как

.IF ax=0

add ax,bx . ENDIF

Неправда ли, весьма удобное нововведение? Впрочем, я по-прежнему считаю, что для начинающего программировать на ассемблере эти операторы принесут скорее вред, чем пользу.

Директива STRUC.

Данная директива предназначена для объединения различных полей под одним именем. Формат ее таков:

имя_структуры STRUC

определение полей

имя_структуры ENDS

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

имя имя_структуры О. В угловых скобках можно указать начальное значение по­лей по порядку. Например:

MSG MESSA <0,0,0,0,0,0,100,100>. Если значение параметров не указывается, то оно обнуляется.

Предположим, в программе записан следующий шаблон структуры:

names struc

name1   DB   12 DUP(O) ■ NAME 2   DB   12 DUP(O)

names ends

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

name_f names <>

После этого я могу обращаться к полям структуры следующим образом:

LEADX,NAME_F.NAME2 - загрузить смещение поля NAME2 в DXh т.п. Резервирование памяти (переменные).

DB-байтО)

DW - слово (2) DD - двойное слово (4) DF - шесть байт (6) DQ - восемь байт (8) DT-десять байт (10)

Порядок следования сегментов. Директивы появились, начиная с версии 5.0. .SEQ - сегменты следуюттому порядку, как они расположены в файле. Такой по­рядок, как известно, действует по умолчанию.

.ALPHA-сегменты следуют в алфавитном порядке.

.DOSSEG - расположение сегментов соответствует принятому в языках высокого уровня фирмы Microsoft. Появилась с версии Masm 6.O. Использование см. главу 24.