0102 0096 DIVDND DW 150 ;Делимое
0104 001B DIVSOR DW 27 ;Делитель
0106 ???? QUOTNT DW ? ;Частное
; ------------------------------------------------
0108 MAIN PROC NEAR
.LALL
DIVIDE DIVDND,DIVSOR,QUOTNT
+ ; AX=делимое, BX=делитель, CX=частное
0108 A1 0102 R + MOV AX,DIVDND ;Загрузить делимое
010B 8B 1E 0104 R + MOV BX,DIVSOR ;Загрузить делитель
010F 2B C9 + SUB CX,CX ;Регистр для частного
0111 + ??0000:
0111 3B C3 + CMP AX,BX ;Делимое < делителя?
0113 72 05 + JB ??0001 ; да - выйти
0115 2B C3 + SUB AX,BX ;Делимое - делитель
0117 41 + INC CX ;Частное + 1
0118 EB F7 + JMP ??0000
011A + ??0001:
011A 89 0E 0106 R + MOV QUOTNT,CX ;Записать результат
011E C3 RET
011F MAIN ENDP
011F CSEG ENDS
END BEGIN
__________________________________________________________________________
Рис.20.4. Использование директивы LOCAL.
ИСПОЛЬЗОВАНИЕ БИБЛИОТЕК МАКРООПРЕДЕЛЕНИЙ
________________________________________________________________
Определение таких макрокоманд, как INIT1 и INIT2 и одноразовое их
использование в программе кажется бессмысленным. Лучшим подходом здесь
является каталогизация собственных макрокоманд в библиотеке на магнитном
диске, используя любое описательное имя, например, MACRO.LIB:
INIT MACRO CSNAME,DSNAME,SSNAME
.
.
ENDM
PROMPT MACRO MESSGE
.
.
ENDM
Теперь для использования любой из каталогизированных макрокоманд вместо
MACRO определения в начале программы следует применять директиву INCLUDE:
INCLUDE C:MACRO.LIB
.
.
INIT CSEG,DATA,STACK
В этом случае ассемблер обращается к файлу MACRO.LIB (в нашем примере) на
дисководе C и включает в программу оба макроопределения INIT и PROMPT.
Хотя в нашем примере требуется только INIT. Ассемблерный листинг будет
содержать копию макроопределения, отмеченного символом C в 30 колонке
LST-файла. Следом за макрокомандой идет ее расширение с объектным кодом и
с символом плюс (+) в 31 колонке.
Так как транслятор с ассемблера является двухпроходовым, то для
обеспечения обработки директивы INCLUDE только в первом проходе (а не в
обоих) можно использовать следующую конструкцию:
IF1
INCLUDE C:MACRO.LIB
ENDIF
IF1 и ENDIF являются условными директивами. Директива IF1 указывает
ассемблеру на необходимость доступа к библиотеке только в первом проходе
трансляции. Директива ENDIF завершает IF-логику. Таким образом, копия
макроопределений не появится в листинге - будет сэкономлено и время и
память.
Программа на рис.20.5 содержит рассмотренные выше директивы IF1,
INCLUDE и ENDIF, хотя в LST-файл ассемблер выводит только директиву ENDIF.
Обе макрокоманды в кодовом сегменте INIT и PROMPT закаталогизированы в
файле MACRO.LIB, т.е. просто записаны друг за другом на дисковый файл по
имени MACRO.LIB с помощью текстового редактора.
Расположение директивы INCLUDE не критично, но она должна появиться
ранее любой макрокоманды из включаемой библиотеки.
__________________________________________________________________________
TITLE MACRO5 (EXE) Проверка директивы INCLUDE
EDIF
; -----------------------------------------------
0000 STACK SEGMENT PARA STACK 'Stack'
0000 20 [????] DW 32 DUP(?)
0040 STACK ENDS
; -----------------------------------------------
0000 DATA SEGMENT PARA 'Data'
0000 54 65 73 74 20 6F MESSGE DB 'Test of macro','$'
66 20 6D 61 63 72
6F 24
000E DATA ENDS
; -----------------------------------------------
0000 CSEG SEGMENT PARA 'Code'
0000 BEGIN PROC FAR
INIT CSEG,DATA,STACK
0000 1E + PUSH DS
0001 3B C0 + SUB AX,AX
0003 50 + PUSH AX
0004 B8 ---- R + MOV AX,DATA
0007 8E D8 + MOV DS,AX
0009 8E C0 + MOV ES,AX
PROMPT MESSGE
000B B4 09 + MOV AH,09 ;Вывод на экран
000D 8D 16 0000 R + LEA DX,MESSGE
0011 CD 21 + INT 21H
0013 CB RET
0014 BEGIN ENDP
0014 CSEG ENDS
END BEGIN
__________________________________________________________________________
Рис.20.5. Использование библиотеки макроопределений.
Директива очистки
-------------------
Директива INCLUDE указывает ассемблеру на включение всех
макроопределений из специфицированной библиотеки. Например, библиотека
содержит макросы INIT, PROMPT и DIVIDE, хотя программе требуется только
INIT. Директива PURGE позволяет "удалить" нежелательные макросы PROMPT и
DIVIDE в текущем ассемблировании:
IF1
INCLUDE MACRO.LIB ;Включить всю библиотеку
ENDIF
PURGE PROMRT,DIYIDE ;Удалить ненужные макросы
...
INIT CSEG,DATA,STACK ;Использование оставшейся макрокоманды
Директива PURGE действует только в процессе ассемблирования и не
оказывает никакого влияния на макрокоманды, находящиеся в библиотеке.
КОНКАТЕНАЦИЯ (&)
________________________________________________________________
Символ амперсанд (&) указывает ассемблеру на сцепление (конкатенацию)
текста или символов. Следующая макрокоманда MOVE генерирует команду MOVSB
или MOVSW:
MOVE MACRO TAG
REP MOVS&TAG
ENDM
Теперь можно кодировать макрокоманду в виде MOVE B или MOVE W. В
результате макрорасширения ассемблер сцепит параметр с командой MOVS и
получит REP MOVSB или REP MOVSW. Данный пример весьма тривиален и служит
лишь для иллюстрации.
ДИРЕКТИВЫ ПОВТОРЕНИЯ: REPT, IRP, IRPC
________________________________________________________________
Директивы повторения заставляют ассемблер повторить блок операторов,
завершаемых директивой ENDM. Эти директивы не обязательно должны находится
в макроопределении, но если они там находятся, то одна директива ENDM
требуется для завершения повторяющегося блока, а вторая ENDM - для
завершения макроопределения.
REPT: Повторение
------------------
Операция REPT приводит к повторению блока операторов до директивы
ENDM в соответствии с числом повторений, указанным в выражении:
REPT выражение
В следующем примере происходит начальная инициализация значения N=0 и
затем повторяется генерация DB N пять раз:
N = 0
REPT 5
N = N + 1
DB N
ENDM
В результате будут сгенерированы пять операторов DB от DB 1 до DB 5.
Директива REPT может использоваться таким образом для определения таблицы
или части таблицы. Другим примером может служить генерация пяти команд
MOVSB, что эквивалентно REP MOVSB при содержимом CX равном 05:
REPT 5
MOVSB
ENDM
IRP: Неопределенное повторение
--------------------------------
Операция IRP приводит к повторению блока команд до директивы ENDM.
Основной формат:
IRP dummy,
Аргументы, содержащиеся в угловых скобках, представляют собой любое число
правильных символов, строк, числовых или арифметических констант.
Ассемблер генерирует блок кода для каждого аргумента. В следующем примере
ассемблер генерирует DB 3, DB 9, DB 17, DB 25 и DB 28:
IRP N,<3, 9, 17, 25, 28>
DB N
ENDM
IRPC: Неопределенное повторение символа
-----------------------------------------
Операция IRPC приводит к повторению блока операторов до директивы
ENDM. Основной формат:
IRPC dummy,string
Ассемблер генерирует блок кода для каждого символа в строке "string". В
следующем примере ассемблер генерирует DW 3, DW 4 ... DW 8:
IRPC N,345678
DW N
ENDM
УСЛОВНЫЕ ДИРЕКТИВЫ
________________________________________________________________
Ассемблер поддерживает ряд условных директив. Ранее нам уже
приходилось использовать директиву IF1 для включения библиотеки только в
первом проходе ассемблирования. Условные директивы наиболее полезны внутри
макроопределений, но не ограничены только этим применением. Каждая
директива IF должна иметь спаренную с ней директиву ENDIF для завершения
IF-логики и возможную директиву ELSE для альтернативного действия:
IFxx (условие)
. __________
. Условный|
ELSE (не обязательное действие) |
. блок |
. __________|
ENDIF (конец IF-логики)
Отсутствие директивы ENDIF вызывает сообщение об ошибке:
"Undeterminated conditional" (незавершенный условный блок). Если
проверяемое условие истинно, то ассемблер выполняет условный блок до
директивы ELSE или при отсутствии ELSE - до директивы ENDIF. Если условие
ложно, то ассемблер выполняет условный блок после директивы ELSE, а при
отсутствии ELSE вообще обходит условный блок.
Ниже перечислены различные условные директивы:
IF выражение Если выражение не равно нулю, ассемблер
обрабатывает операторы в условном блоке.
IFE выражение Если выражение равно нулю, ассемблер обрабатывает
операторы в условном блоке.
IF1 (нет выражения) Если осуществляется первый проход ассемблирования
то обрабатываются операторы в условном блоке.
IF2 (нет выражения) Если осуществляется второй проход операторы
ассемблирования, то обрабатываются в условном
блоке.
IFDEF идентификатор Если идентификатор определен в программе или
объявлен как EXTRN, то ассемблер обрабатывает
операторы в условном блоке.
IFNDEF идентификатор Если идентификатор не определен в программе или
не объявлен как EXTRN, то ассемблер обрабатывает
операторы в условном блоке.