Ассемблер и программирование для IBM PC

       

Макросредства


------------------------------------------------------------

Макросредства

Цель: Объяснить определение и использование ассемблерных макрокоманд.

ВВЕДЕНИЕ ------------------------------------------------------------

Для каждой закодированной команды ассемблер генерирует одну команду на машинном языке. Но для каждого закодированного оператора компиляторного языка Pascal или C генерируется один или более (чаще много) команд машинного языка. В этом отношении можно считать, что компиляторный язык состоит из макро операторов. Ассемблер MASM также имеет макросредства, но макросы здесь определяются программистом. Для этого задается имя макроса, директива MACRO, различные ассемблерные команды, которые должен генерировать данный макрос и для завершения макропределения - директива MEND. Затем в любом месте программы, где необходимо выполнение определенных в макроко манде команд, достаточно закодировать имя макроса. В резуль тате ассемблер сгенерирует необходимые команды.

Использование макрокоманд позволяет: - упростить и сократить исходный текст программы; - сделать программу более понятной; - уменьшить число возможных ошибок кодирования.

Примерами макрокоманд могут быть операции ввода-вывода, связанные с инициализацией регистров и выполнения прерываний преобразования ASCII и двоичного форматов данных, арифмети ческие операции над длинными полями, обработка строковых данных, деление с помощью вычитания. В данной главе рассмотрены особенности макросредств, включая те, которые не достаточно ясно даны в руководстве по ассемблеру. Тем не менее пояснения для некоторых малоисполь зуемых операций следует искать в руководстве по ассеблеру.

ПРОСТОЕ МАКРООПРЕДЕЛЕНИЕ ------------------------------------------------------------

Макроопределение должно находиться до определения сегмента. Рассмотрим пример простого макроопределения по имени INIT1, которое инициализирует сегментные регистры для EXE-программы:

INIT1 MACRO ;Начало ASSUME CS:CSEG,DS:DSEG,SS:STACK;ES:DSEG ; \ PUSH DS ; \


Ассемблер для IBM PC. Глава 20 19
SUB AX,AX ; \ PUSH AX ;Тело \ MOV AX,DSEG ;макро/ MOV DS,AX ; / MOV ES,AX ; / ENDM ;Конец


Директива MACRO указывает ассемблеру, что следующие команды до директивы ENDM являются частью макроопределения. Имя маккрокоманды - INIT1, хотя здесь возможны другие правильные уникальные ассемблерные имена. Директива ENDM завершает макроопределение. Семь команд между директивами MACRO и ENDM составляют тело макроопределения. Имена, на которые имеются ссылки в макроопределении, CSEG, DSEG и STACK должны быть определены где-нибудь в другом месте программы. Макрокоманда INIT1 может использо ваться в кодовом сегменте там, где необходимо инициализиро вать регистры. Когда ассемблер анализирует команду INIT1, он сначала просматривает таблицу мнемокодов и, не обнаружив там соответствующего элемента, проверяет макрокоманды. Так как программа содержит определение макрокоманды INIT1 ассем блер подставляет тело макроопределения, генерируя необходи мые команды - макрорасширение. Программа использует рассматриваемую макрокоманду только один раз, хотя имеются другие макрокоманды, предназначенные на любое число применений и для таких макрокоманд ассемблер генерирует одинаковые макрорасширения. На рис.20.1 показана ассемблированная программа. В листин ге макрорасширения каждая команда, помеченная слева знаком плюс (+), является результатом генерации макрокоманды. Кроме того, в макрорасширении отсутствует директива ASSUME, так как она не генерирует объектный код. В последующем разделе "Включение из библиотеки макро определений показана возможность каталогизации макрокоманд в библиотеке и автоматическое включение их в любые программы.
------------------------------------------------------------ ------------------------------------------------------------ Рис.20.1. Пример ассемблирования макрокоманды.
ИСПОЛЬЗОВАНИЕ ПАРАМЕТРОВ В МАКРОКОМАНДАХ ------------------------------------------------------------
В предыдущем макроопределении требовались фиксированные имена сегментов: CSEG, DSEG и STACK. Для того, чтобы макро команда была более гибкой и могла принимать любые имена сегментов, определим эти имена, как формальные параметры:


INIT2 MACRO CSNAME,DSNAME,SSNAME ;Формальные параметры ASSUME CS:CSNAME,DS:DSNAME,SC:SSNAME,ES:DSNAME PUSH DS SUB AX,AX PUSH AX
Ассемблер для IBM PC. Глава 20 20
MOV AX,DSNAME MOV DS,AX MOV ES,AX ENDM ;Конец макроопределения
Формальные параметры в макроопределении указывают ассемблеру на соответствие их имен любым аналогичным именам в теле макроопределения. Все три формальных параметра CSNAME, DSNAME и SSNAME встречаются в директиве ASSUME, а параметр DSNAME еще и в последующей команде MOV. Формальные параметры могут иметь любые правильные ассемблерные имена, не обязательно совпадающими именами в сегменте данных. Теперь при использовании макрокоманды INIT2 необходимо указать в качестве параметров действительные имена трех сегментов в соответствующей последовательности. Например, следующая макрокоманда содержит три параметра, которые соответствуют формальным параметрам в исходном макроопреде лении:
Макроопределение: INIT2 MACRO CSNAME,DSNAME,SSNAME (формальные параметры) Макрокоманда: | | | INIT2 CSEG,DSEG,STACK (параметры)
Так как ассемблер уже определил соответствие между формальны ми параметрами и операторами в макроопределении, то теперь ему остается подставить параметры макрокоманды в макрорасши рении:
- Параметр 1: CSEG ставится в соответствие с CSNAME в макроопределении. Ассемблер подставляет CSEG вместо CSNAME в директиве ASSUME.
- Параметр 2: DSEG ставится в соответствие с DSNAME в макроопределении. Ассемблер подставляет DSEG вместо двух DSNAME: в директиве ASSUME и в команде MOV.
- Параметр 3: STACK ставится в соответствие с SSNAME в макроопределении. Ассемблер подставляет STACK вместо SSNAME в директиве ASSUME.
Макроопределение с формальными параметрами и соответствую щее макрорасширение приведены на рис.20.2.
------------------------------------------------------------ ------------------------------------------------------------ Рис.20.2. Использование параметров в макрокомандах.
Формальный параметр может иметь любое правильное ассемблерное имя (включая имя регистра, например, CX), которое в процессе ассемблирования будет заменено на параметр макрокоманды. Отсюда следует, что ассемблер не распознает регистровые имена и имена, определенные в области


Ассемблер для IBM PC. Глава 20 21
данных, как таковые. В одной макрокоманде может быть определено любое число формальных парамтеров, разделенных запятыми, вплоть до 120 колонки в строке.
КОММЕНТАРИИ ------------------------------------------------------------
Для пояснений назначения макроопределения в нем могут находиться комментарии. Директива COMMENT или символ точка с запятой указывают на строку комментария, как это показано в следующем макроопределении PROMPT:
PROMPT MACRO MESSGE ; Эта макрокоманда выводит сообщения на экран MOV AH,09H LEA DX,MESSGE INT 21H ENDM
Так как по умолчанию в листинг попадают только команды генерирующие объектный код, то ассемблер не будет автомати чески выдавать и комментарии, имеющиеся в макроопределении. Если необходимо, чтобы в расширении появлялись комментарии, следует использовать перед макрокомандой директиву .LALL ("list all" - выводить все), которая кодируется вместе с лидирующей точкой: .LALL PROMPT MESSAG1
Макроопределение может содержать несколько комментариев, причем некоторые из них могут выдаваться в листинге, а другие - нет. В первом случае необходимо использовать директиву .LALL. Во втором - кодировать перед комментарием два символа точка с запятой (;;) - признак подавления вывода комментария в листинг. По умолчанию в ассемблере действует директива .XALL, которая выводит в листинг только команды, генерирующие объектный код. И, наконец, можно запретить появление в листинге ассемблерного кода в макрорасширениях, особенно при использовании макрокоманды в одной программе несколько раз. Для этого служит директива .SALL ("suppress all" - подавить весь вывод), которая уменьшает размер выводимого листинга, но не оказывает никакого влияния на размер объектного модуля. Директивы управления листинком .LALL, .XALL, .SALL сохраняют свое действие по всему тексту программы, пока другая директива листинга не изменит его. Эти директивы можно размещать в программе так, чтобы в одних макрокомандах распечатывались комментарии, в других - макрорасширения, а в третьих подавлялся вывод в листинг. Программа на рис.20.3 демонстрирует описанное выше свойство директив листинга. В программе опредлелено два макроопределения INIT2 и PROMPT, расмотренные ранее. Кодовый сегмент содержит директиву .SALL для подавления распечатки


Ассемблер для IBM PC. Глава 20 22
INIT2 и первого расширения PROMPT. Для второго расширения PROMPT директива .LALL указывает ассемблеру на вывод в листинг комментария и макрорасширения. Заметим, однако, что комментарий, отмеченный двумя символами точка с запятой (;;) в макроопределении PROMPT, не распечатывается в макрорасшире ниях независимо от действия директив управления листингом.
------------------------------------------------------------ ------------------------------------------------------------ Рис.20.3. Распечатка и подавление макрорасширений в листинге.
ИСПОЛЬЗОВАНИЕ МАКРОКОМАНД В МАКРООПРЕДЕЛЕНИЯХ ------------------------------------------------------------
Макроопределение может содержать ссылку на другое макроопределение. Рассмотрим простое макроопределение DOS21, которое заносит в регистр AH номер функции DOS и выполняет INT 21H:
DOS21 MACRO DOSFUNC MOV AH,DOSFUNC INT 21H ENDM
Для использования данной макрокоманды при вводе с клавиатуры необходимо закодировать:
LEA DX,NAMEPAR DOS21 0AH
Предположим, что имеется другое макроопределение, использую щее функцию 02 в регистре AH для вывода символа:
DISP MACRO CHAR MOV AH,02 MOV DL,CHAR INT 21H ENDM
Для вывода на экран, например, звездочки достаточно закодиро вать макрокоманду DISP '*'. Можно изменить макроопределение DISP, воспользовшись макрокомандой DOC21:
DISP MACRO CHAR MOV DL,CHAR DOS21 02 ENDM
Теперь, если закодировать макрокоманду DISP в виде DISP '*', то ассемблер сгенерирует следующие команды:
MOV DL,'*'
Ассемблер для IBM PC. Глава 20 23
MOV AH,02 INT 21H
ДИРЕКТИВА LOCAL ------------------------------------------------------------
В некоторых макрокомандах требуется определять элементы данных или метки команд. При использовании такой макрокоманды в программе более одного раза происходит также неоднократное определение одинаковых полей данных или меток. В результате ассемблер выдаст сообщения об ошибке из-за дублирования имен. Для обеспечения уникальности генерируемых в каждом макрорасширении имен используется директива LOCAL, которая кодируется непосредственно после директивы MACRO, даже перед комментариями. Общий формат имеет следующий вид:


LOCAL dummy-1,dummy-2,... ;Формальные параметры
Рис.20.4. иллюстрирует использование директивы LOCAL. В приведенной на этом рисунке программе выполняется деление вычитанием; делитель вычитается из делимого и частное увеличивается на 1 до тех пор, пока делимое больше делителя. Для данного алгоритма необходимы две метки: COMP - адрес цикла, OUT - адрес выхода из цикла по завершению. Обе метки COMP и OUT определены как LOCAL и могут иметь любые правильные ассемблерные имена. В макрорасширении для COMP генерируется метка ??0000, а для OUT - ??0001. Если макрокоманда DIVIDE будет использова на в этой программе еще один раз, то в следующем макрорасши рении будут сгенерированы метки ??0002 и ??0003 соответствен но. Таким образом, с помощью директивы LOCAL обеспечивается уникальность меток в макрорасширениях в одной программе.
------------------------------------------------------------ ------------------------------------------------------------ Рис.20.4. Использование директивы LOCAL.
ИСПОЛЬЗОВАНИЕ БИБЛИОТЕК МАКРООПРЕДЕЛЕНИЙ ------------------------------------------------------------
Определение таких макрокоманд, как INIT1 и INIT2 и одноразовое их использование в программе кажется бессмысленным. Лучшим подходом здесь является каталогизация собственных макрокоманд в библиотеке на магнитном диске, используя любое описательное имя, например, MACRO.LIB:
INIT MACRO CSNAME,DSNAME,SSNAME . . ENDM PROMPT MACRO MESSGE . .
Ассемблер для IBM PC. Глава 20 24
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 не критично, но она должна появиться ранее любой макрокоманды из включаемой библиотеки.
------------------------------------------------------------ ------------------------------------------------------------ Рис.20.5. Использование библиотеки макроопределений.
Директива очистки
Директива INCLUDE указывает ассемблеру на включение всех макроопределений из специфицированной библиотеки. Например, библиотека содержит макросы INIT, PROMPT и DIVIDE, хотя
Ассемблер для IBM PC. Глава 20 25
программе требуется только 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
Ассемблер для IBM PC. Глава 20 26
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,<arguments>
Аргументы, содержащиеся в угловых скобках, представляют собой любое число правильных символов, строк, числовых или арифметических констант. Ассемблер генерирует блок кода для каждого аргумента. В следующем примере ассемблер генерирует 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 для включения библиотеки только в первом проходе ассемблирования. Условные


Ассемблер для IBM PC. Глава 20 27
директивы наиболее полезны внутри макроопределений, но не ограничены только этим применением. Каждая директива IF должна иметь спаренную с ней директиву ENDIF для завершения IF-логики и возможную директиву ELSE для альтернативного действия:
IFxx (условие) . } . } Условный ELSE (не обязательное действие) } . } блок . } ENDIF (конец IF-логики)
Отсутствие директивы ENDIF вызывает сообщение обошибке: "Undeterminated conditional" (незавершенный условный блок). Если проверяемое условие истино, то ассемблер выполняет условный блок до директивы ELSE или при отсутствии ELSE - до директивы ENDIF. Если условие ложно, то ассемблер выполняет условный блок после директивы ELSE, а при отсутствии ELSE вообще обходит условный блок. Ниже перечислены различные условные директивы:
IF выражение Если выражение не равно нулю, ассемблер обрабатывает операторы в условном блоке. IFE выражение Если выражение равно нулю, ассемблер обрабатывает операторы в условном блоке. IF1 (нет выражения) Если осуществляется первый проход ассемблирования, то обрабатываются операторы в условном блоке. IF2 (нет выражения) Если осуществляется второй проход ассемблирования, то обрабатываются операторы в условном блоке. IFDEF идентификатор Если идентификатор определен в программе или объявлен как EXTRN, то ассемблер обрабатывает операторы в условном блоке. IFNDEF идентификатор Если идентификатор не определен в программе или не объявлен как EXTRN, то ассемблер обрабатывает операторы в условном блоке. IFB <аргумент> Если аргументом является пробел, ассемблер обрабатывает операторы в условном блоке. Аргумент должен быть в угловых скобках. IFNB <аргумент> Если аргументом является не пробел, то ассемблер обрабатывает операторы в условном блоке. Аргумент должен быть в угловых скобках.
Ассемблер для IBM PC. Глава 20 28
IFIDN <арг-1>,<арг-2> Если строка первого аргумента идентична строке второго аргумента, то ассемблер обрабатывает операторы в условном блоке. Аргументы должны быть в угловых скобках. IFDIF<арг-1>,<арг-2> Если строка первого аргумента отличается от строки второго аргумента, то ассемблер обрабатывает операторы в условном блоке. Аргументы должны быть в угловых скобках.


Ниже приведен простой пример директивы IFNB (если не пробел). Для DOS INT 21H все запросы требуют занесения номера функции в регистр AH, в то время как лишь некоторые из них используют значение в регистре DX. Следующее макроопределение учитывает эту особенность:
DOS21 MACRO DOSFUNC,DXADDRES MOV AN,DOSFUNC IFNB <DXADDRES>
MOV DX,OFFSET DXADDRES ENDIF INT 21H ENDM
Использование DOS21 для простого ввода с клавиатуры требует установки значения 01 в регистр AH:
DOS21 01
Ассемблер генерирует в результате команды MOV AH,01 и INT 21H. Для ввода символьной строки требуется занести в регистр AH значение 0AH, а в регистр DX - адрес области ввода:
DOS21 0AH,IPFIELD
Ассемблер генерирует в результате обе команды MOV и INT 21H.
ДИРЕКТИВА ВЫХОДА ИЗ МАКРОСА EXITM. ------------------------------------------------------------
Макроопределение может содержать условные дерективы, которые проверяют важные условия. Если условие истинно, то ассемблер должен прекратить дальнейшее макрорасширение. Для этой цели служит директива EXITM:
IFxx [условие] . . (неправильное условие) . EXITM . .
Ассемблер для IBM PC. Глава 20 29
ENDIF
Как только ассемблер попадает в процессе генерации макро расширения на директиву EXITM, дальнейшое расширение прекращается и обработка продолжается после директивы ENDM. Можно использовать EXITM для прекращения повторений по директивам REPT, IRP и IRPC даже если они находятся внутри макроопределения.
МАКРОКОМАНДЫ, ИСПОЛЬЗУЮЩИЕ IF И IFNDEF УСЛОВИЯ ------------------------------------------------------------
Программа на рис.20.6 содержит макроопределение DIVIDE, которая генерирует подпрограмму для выполнения деления вычитанием. Макрокоманда должна кодироваться с параметрами в следующей последовательности: делимое, делитель, частное. Макрокоманда содержит директиву IFNDEF для проверки наличия параметров. Для любого неопределенного элемента макрокоманда увеличивает счетчик CNTR. Этот счетчик может иметь любое корректное имя и предназначен для временного использования в макроопределении. После проверки всех трех параметров, макрокоманда проверяет CNTR:


IF CNTR ; Макрорасширение прекращено EXITM
Если счетчик CNTR содержит ненулевое значение, то ассемблер генерирует комментарий и прекращает по директиве EXITM дальнейшее макрорасширение. Заметим, что начальная команда устанавливает в счетчике CNTR нулевое значение и, кроме того, блоки IFNDEF могут устанавливать в CNTR единичное значение, а не увеличивать его на 1. Если ассемблер успешно проходит все проверки, то он генерирует макрорасширение. В кодовом сегменте первая макрокоманда DIVIDE содержит правильные делимое и частное и, поэтому генерирует только комментарии. Один из способов улучшения рассматриваемой макрокоманды - обеспечить проверку на ненулевой делитель и на одинаковый знак делимого и делителя; для этих целей лучше использовать коды ассемблера, чем условные директивы.
------------------------------------------------------------ ------------------------------------------------------------ Рис.20.6. Использование директив IF и IFNDEF.
МАКРОС, ИСПОЛЬЗУЮЩИЙ IFIDN-УСЛОВИЕ ------------------------------------------------------------
Ассемблер для IBM PC. Глава 20 30
Программа на рис.20.7 содержит макроопределение по имени MOVIF, которая генерирует команды MOVSB или MOVSW в зависимости от указанного параметра. Макрокоманду можно кодировать с параметром B (для байта) или W (для слова) для генерации команд MOVSB или MOVSW из MOVS. Обратите внимание на первые два оператора в макроопределе нии: MOVIF MACRO TAG IFIDN <&TAG>,<B>
Условная директива IFIDN сравнивает заданный параметр (предположительно B или W) со строкой B. Если значения идентичны, то ассемблер генерирует REP MOVSB. Обычное использование амперсанда (&) - для конкатенации, но в данном примере операнд <TAG> без амперсанда не будет работать. Если в макрокоманде не будет указан параметр B или W, то ассемблер сгенерирует предупреждающий комментарий и команду MOVSB (по умолчанию). Примеры в кодовом сегменте трижды проверяют макрокоманду MOVIF: для параметра B, для параметра W и для неправильного параметра. Не следует делать попыток выполнения данной программы в том виде, как она приведена на рисунке, так как регистры CX и DX не обеспечены правильными значениями. Предполагается, что рассматриваемая макрокоманда не является очень полезной и ее назначение здесь - проиллюстри ровать условные директивы в простой форме. К данному моменту, однако, вы имеете достаточно информации для составления больших полезных макроопределений.


------------------------------------------------------------ ------------------------------------------------------------ Рис.20.7. Использование директивы IFIDN
ОСНОВНЫЕ ПОЛОЖЕНИЯ НА ПАМЯТЬ ------------------------------------------------------------
ъ Макросредства возможны только для полной версии ассемблера (MASM). ъ Использование макрокоманд в программах на ассемблере дает в результате более удобочитаемые программы и более произ водительный код. ъ Макроопределение состоит из директивы MACRO, блока из одного или нескольких операторов, которые генерируются при макрорасширениях и директивы ENDM для завершения определения. ъ Код, который генерируется в программе по макрокоманде, представляет собой макрорасширение. ъ Директивы .SALL,.LALL и .XALL позволяют управлять распечаткой комментариев и генерируемого объектного кода в макрорасширении. ъ Директива LOCAL позволяет использовать имена внутри макроопределений. Директива LOCAL кодируется непосредственно после директивы MACRO.
Ассемблер для IBM PC. Глава 20 31
ъ Использование формальных параметров в макроопределении позволяет кодировать параметры, обеспечивающие большую гибкость макросредств. ъ Библиотека макроопределений дает возможность использо вать макрокоманды для различных ассемблерных программ. ъ Условные директивы позволяют контролировать параметры макрокоманд.
ВОПРОСЫ ДЛЯ САМОПРОВЕРКИ ------------------------------------------------------------
20.1. Напишите необходимые директивы: а) для подавления всех команд, которые генерирует макрокоманда и б) для распечатки только команд, генерирующих объектный код. 20.2. Закодируйте два макроопределения для умножения: а) MULTBY должна генерировать код для умножения байта на байт; б) MULTWD должна генерировать код для умножения слова на слово. Для множителя и множимого используйте в макро определении формальные параметры. Проверьте выполнение макрокоманд на небольшой программе, в которой также определены необходимые области данных. 20.3. Запишите макроопределения из вопроса 20.2 в "макро библиотеку". Исправьте программу для включения элементов библиотеки по директиве INCLUDE в первом проходе ассемблирования. 20.4. Напишите макроопределение BIPRINT, использующей BIOS INT 17H для печати. Макроопределение должно включать проверку состояния принтера и обеспечивать печать любых строк любой длины. 20.5. Измените макроопределение на рис.20.6 для проверки делителя на ноль (для обхода деления).
Ассемблер для IBM PC. Глава 21 1


    Содержание раздела