LAB_9_2014c (1075931), страница 2
Текст из файла (страница 2)
XOR p,p
ENDM
1 XOR AX,AX
1 XOR BX,BX
1 XOR CX,CX
1 XOR DX,DX
Жирным шрифтом текста показан код на макроязыке, а обычным макрорасширения. Другой пример иллюстрирует задание выражений в списке фактических параметров для директивы IRP. Здесь используются специальные символы и вспомогательные переменные этапа компиляции (N и W4), которым предварительно задаются значения ( 3 и 5 соответственно, с помощью присваивания и директивы эквивалентности).
N = 3
W4 EQU 5
IRP A, <N+1, %N + 1, W%N+1, %N , N , %W4> ; Пять выражений
DW A
ENDM
1 DW N+1
1 DW 4
1 DW W4
1 DW 3
1 DW N
1 DW 5
Служебный символ “%” позволяет взять значение переменной в выражении, об этих символах мы поговорим ниже. На втором уровне выделена подстановка значения переменной этапа компиляции W4.
Директива IRPC имеет следующий синтаксис:
IRPС <переменная цикла>,<Строка символов >
<тело цикла>
ENDM
<Строка символов > := <символ> | < Строка символов >
Для этого циклического оператора макроассемблера, переменной цикла (D) присваивается значение символа из строки перечисления и с каждым значением переменной из списка цикл выполняется. Число повторений цикла равно числу символов в строке. Пример использования циклического оператора:
IRPC D, 123456789 ; Девять сиволов цикла
V1&D DB D
ENDM
1 V11 DB 1
1 V12 DB 2
1 V13 DB 3
1 V14 DB 4
1 V15 DB 5
1 V16 DB 6
1 V17 DB 7
1 V18 DB 8
1 V19 DB 9
Формальный параметр “D” является одновременно переменной цикла. Для каждого символа из строки генерируется описание в виде байтовой переменной. В этом примере используется служебный символ макрокоманд “&”, который позволяет сливать имена переменных.
10 Локальные метки и переменные макрокоманд
При разработке макрокоманд могут использоваться вспомогательные метки и переменные. Так как макрокоманда может быть вызвана несколько раз, то при совпадении имен будет выдана ошибка и компиляция остановится. Для автоматической индексации таких имен используется специальный механизм локальных переменных. Для его использования внутри макроопределения задается директива макрокоманд LOCAL, которая имеет следующий синтаксис:
LOCAL <локальное имя> {,< локальное имя > … }
В качестве локального имени могут использоваться локальные переменные или локальные метки. Компилятор заменяет эти имена служебными идентификаторами (??dddd, где d – десятичная цифра) и обеспечивает сквозную нумерацию во всем исходном модуле. Так исключается дублирование описаний. Покажем применение локальных меток и переменных на примере. Пусть имеется макроопределение:
print MACRO CH, CR
LOCAL loc_per , loc_met
MOV DL, CH
MOV loc_per , DL
CALL DISPL
IFIDN <CR>,<PER>
CALL crlf
ENDIF
JMP loc_met
loc_per db 0
loc_met:
ENDM
В этом макроопределении объявлена локальная метка (loc_met) и переменная (loc_per). При вызове макрокоманды мы получим в листинге следующие макрорасширения:
print '5', PER
1 MOV DL, '5'
1 MOV ??0000 , DL
1 CALL DISPL
1 CALL crlf
1 JMP ??0001
1 ??0000 db 0
1 ??0001:
В следующем вызове этой же макрокоманды print в том же модуле программы Ассемблета метки и переменные будут проиндексированы (вместо ??0000 будет ??0002):
print '7', PER
1 MOV DL, '7'
1 MOV ??0002 , DL
1 CALL DISPL
1 CALL crlf
1 JMP ??0003
1 ??0002 db 0
1 ??0003:
Общее число локальных меток и переменных во всех макрорасширениях одного исходного модуля, не может превышать 9999.
11 Служебные символы макрокоманд
Специальные служебные символы применяются для написания макрокоманд для достижения следующих целей:
-
“%” - данный символ позволяет получить значение числовой или текстовой переменной этапа компиляции и вставить его в макрорасширение. Он работает в макрокомандах и циклах этапа компиляции.
-
“&” - позволяет склеить строку символов и переменную этапа компиляции или параметр макроопределения (или наоборот).
-
“!” - используется в аргументе для указания Ассемблеру, что символ, следующий за ним, является литералом, а не именем (параметра, переменной этапа компиляции).
-
“<” “>” – используется для задания текста, который передается в макрорасширения целиком, даже если он содержит пробелы и другие знак операций.
-
“;;” - используются для включения комментария в текст макроопределения. Эти комментарии не передаются в макрорасширения.
Рассмотрим примеры. Служебные символы “%” и скобки “<” “>”. Если переменная символьная. Знак процента позволяет взять значение переменной этапа компиляции, вне зависимости от того как она задается. Для оператора EQU мы получим:
L EQU <'&text'>
IRP D,<%L, L >
DB D
ENDM
1 DB '&text'
1 DB L
При использовании числовой переменной, задаваемой присваиванием, получим следующее расширение:
L = 2
IRP D,<%L, L >
DB D
ENDM
1 DB 2
1 DB L
Служебный символ “&”. Опишем макрокоманду для генерации макрокоманд MOVSB и MOVSW. Проверим ее вызовы двумя разными параметрами.
; Описание макрокоманды
MOVE MACRO TAG
REP MOVS&TAG
ENDM
;; Вызов макрокоманды и расширение
MOVE W
1 REP MOVSW
MOVE B
1 REP MOVSB
Служебный символ “&” используется для слияния константы и формального параметра макрокоманды (TAG). Следующая макрокоманда иллюстрирует использование почти всех служебных символов (“&” , “%” , “%”).
TESTPR MACRO PAR1 , PAR2 , V ; Три параметра в заголовке
LOCAL MET, MSG
; Вызов по параметру
MOV AH , 09H
MOV DX , OFFSET PAR1
INT 21H
;; Вызов по локальному параметру
MOV AH , 09H
MOV DX , OFFSET MSG
INT 21H
JMP MET
MSG DB '&PAR2 ---','!&V ,&V , %V,!%V'
MET:
ENDM
Параметры PAR1 и PAR2 вставляются в макрорасширение по значению. Пример вызова:
MSG5 DB 'TEST$',10,13
…
.LALL
TESTPR MSG5 , <Пример текста !%V> , 1 ; Вызов макрокоманды
1 ; Вызов по параметру
1 MOV AH , 09H
1 MOV DX , OFFSET MSG5
1 INT 21H
1 MOV AH , 09H
1 MOV DX , OFFSET ??0008
1 INT 21H
1 JMP ??0007
1 ??0008 DB 'Пример текста %V ---','!1 ,1 , %V , !%V'
1 ??0007:
В этом примере используются при вызове макрокоманды угловые скобки, для передачи в макрокоманду текста с несколькими пробелами. В примере видно, что параметры &V будет заменены (в примере на 1). Параметр в тексте %V должен в передаваемом тексте (PAR2) быть помечен знаком “!”, в противном случае будет отмечена ошибка (он будет интерпретирован как литерал). Значение &PAR1 и просто PAR1 в этом примере являются эквивалентными (проверьте!).
12 Переопределение и удаление макрокоманд
В процессе одной макрогенерации можно переопределить макрос. Для этого достаточно задать новое макроопределение с таким же именем. Например:
;; Описание первого макроса
A MACRO V1
INC V1
ENDM
;; Вызов первого макроса А
A AH
Расширение:
1 INC AH
;; Описание/переопределение второго макроса А
A MACRO V1,V2
INC V1
DEC V2
ENDM
;; Вызов второго макроса А
A AH,AL
Расширение:
1 INC AH
1 DEC AL
Директива PURGE исключает макрос из списка доступных на данный момент макрогенерации:
;; Удаление макроса А и дальнейшая попытка его запустить
PURGE A
A AX
Расширение:
…
Расцирения нет, так как данный макрос выключен, а в окне ошибок появляется предупреждение.
13 Вложенные вызовы макрокоманд
Из одних макрокоманд можно вызывать другие макрокоманды. Такие вызовы называются вложенными. Использование воженных макрокоманд позволяет сделать настройки программы более гибкими и сократить размеры макрокоманд. Рассмотрим пример. Первая макрокоманда заполняет поле значением параметра.
; Макрокоманда выделения памяти c заполнением выражением (VAR)
FIELD MACRO VAR
DB &VAR
ENDM
Во второй макрокоманде организован цикл заполнения массива (NAME). Натуральными числами в порядке возрастания, начиная с базового значения (BASE), с определенным шагом (STEP) и определенного размера (SIZEM).
; Натуральные числа в порядке возрастания
MAS MACRO SIZEM , NAME , BASE , STEP
FCount = BASE
&NAME DB BASE
REPT SIZEM - 1
FIELD %FCount + STEP ; Вызов макрокоманды для описания и заполнения поля
FCount = FCount + 1
ENDM
ENDM
При вызове макрокоманды мы получим следующее расширение:
MAS 10 , T0 , 3 , 5 ; 5 шаг данных
1 T0 DB 3
3 DB 8
3 DB 9
3 DB 10
3 DB 11
3 DB 12
3 DB 13
3 DB 14
3 DB 15
3 DB 16
Макрокоманда генерирует массив T0 размером в 10 элементов, начиная с 3 с шагом 5.
14 Директивы условной компиляции
Директивы условной компиляции позволяют включать или не включать текст в исходную программу в зависимости от разнообразных условий, а также выбирать альтернативный вариант включения текста . Перечень групп директив (они разделены по типам условий) приведен ниже:
-
IF1, IF2, ELSE, ENDIF – директивы условной компиляции, выделяют разные проходы исходного текста программы компилятором (первый, второй).
-
IF, IFE, ELSE, ENDIF – директивы условной компиляции, основанные на логическом условии этапа компиляции.
-
IFDEF , IFNDEF, ELSE, ENDIF – директивы условной компиляции, базирующиеся на возможном объявлении (описании, задании ) переменных этапа компиляции.
-
IFB, IFNB, ELSE, ENDIF – директивы условной компиляции, применительно к параметрам макрокоманд, включающие проверку наличия или отсутствия параметров макрокоманды.
-
IFIDN, IFIDIF, ELSE, ENDIF - директивы условной компиляции, выполняющие сравнение переменных этапа компиляции.
Рассмотрим кратко возможности директив условной компиляции. В общем виде для всех директив задается следующая конструкция:
IFXX <аргументы условного оператора>
<директивы для включения в текст программы при истинности условий>
ENDIF
Обозначение IFXX заменяет все разновидности директив условной компиляции.
Директивы IF1, IF2 включают текст в исходную программу, если выполняется первый (IF1) или второй (IF2) проход компилятора. Обычно это делается при подключении библиотек макрокоманд, так как повторное включение приводить к ошибкам. Например:
IF1
INCLUDE MACRO.LIB
ENDIF
Макробиблиотека MACRO.LIB для нашего примера будет включена в текст исходного модуля только на первом проходе компилятора.
Директивы IF, IFE, ELSE, ENDIF включают текст в исходную программу, на основе логических условий этапа компиляции. Если условие выполнено (равно нулю для IFE), то текст в исходную программу включается. Если условие не выполнено (не равно нулю для IF), то текст в исходную программу включается. Конструкция ELSE позволяет задать альтернативу по этому условию. Синтаксис и семантика директив задан ниже:
IF <логическое выражение>
<операторы условного блока>
ENDIF
Если значение логического выражения не нулевое (истина в Ассемблере ), операторы условного блока включаются в исходный модуль программы.
IFE < логическое выражение>
<операторы условного блока>
ENDIF
Если значение логического выражения равно нулю, операторы условного блока включаются в исходный модуль программы.
Значения истина и ложь в Ассемблере определяются так:
FALSE (0000h) - ложь
TRUE (FFFFh) - истина
В общем виде конструкции всех условных директив можно описать и так, с учетом возможности альтернативных включений текста:
IFXX <аргументы>
<директивы для истинного значения условия>