19.1. Напишите программу в расширенной версии DOS для а) прогона
страницы; б) печати вашего имени; в) перевода строки и печати вашего
адреса; г) перевода строки и печати названия вашего города/штата
(республики); д) прогона страницы.
19.2. Переделайте программу из предыдущего вопроса для базовой версии
DOS.
19.3. Закодируйте строку, в которой имеется следующая информация:
возврат каретки, прогон страницы, включение узких букв, заголовок (любое
имя) и выключение узких букв.
19.4. Измените программу из вопроса 19.1 для использования BIOS INT
17H. Обеспечьте проверку состояния принтера.
19.5. Измените программу из вопроса 19.1 так, чтобы пункты б), в), г)
выполнялись по 5 раз.
19.6. Измените программу на рис.19.1 для выполнения в базовой версии
DOS.
19.7. Измените программу на рис.19.2 так, чтобы распечатываемые
строки также выводились на экран.
ГЛАВА 20 Макросредства
__________________________________________________________________________
Ц е л ь: Объяснить определение и использование ассемблерных
макрокоманд.
ВВЕДЕНИЕ
________________________________________________________________
Для каждой закодированной команды ассемблер генерирует одну команду
на машинном языке. Но для каждого закодированного оператора компиляторного
языка Pascal или C генерируется один или более (чаще много) команд
машинного языка. В этом отношении можно считать, что компиляторный язык
состоит из макрооператоров.
Ассемблер MASM также имеет макросредства, но макросы здесь
определяются программистом. Для этого задается имя макроса, директива
MACRO, различные ассемблерные команды, которые должен генерировать данный
макрос и для завершения макроопределения - директива MEND. Затем в любом
месте программы, где необходимо выполнение определенных в макрокоманде
команд, достаточно закодировать имя макроса. В результате ассемблер
сгенерирует необходимые команды.
Использование макрокоманд позволяет:
- упростить и сократить исходный текст программы;
- сделать программу более понятной;
- уменьшить число возможных ошибок кодирования.
Примерами макрокоманд могут быть операции ввода-вывода, связанные с
инициализацией регистров и выполнения прерываний преобразования ASCII и
двоичного форматов данных, арифметические операции над длинными полями,
обработка строковых данных, деление с помощью вычитания.
В данной главе рассмотрены особенности макросредств, включая те,
которые не достаточно ясно даны в руководстве по ассемблеру. Тем не менее
пояснения для некоторых малоиспользуемых операций следует искать в
руководстве по ассемблеру.
ПРОСТОЕ МАКРООПРЕДЕЛЕНИЕ
________________________________________________________________
Макроопределение должно находиться до определения сегмента.
Рассмотрим пример простого макроопределения по имени INIT1, которое
инициализирует сегментные регистры для EXE-программы:
INIT1 MACRO ;Начало
ASSUME CS:CSEG,DS:DSEG,SS:STACK;ES:DSEG ;________________
PUSH DS ; |
SUB AX,AX ; |
PUSH AX ;Тело |
MOV AX,DSEG ;макроопpеделения|
MOV DS,AX ; |
MOV ES,AX ;________________|
ENDM ;Конец
Директива MACRO указывает ассемблеру, что следующие команды до
директивы ENDM являются частью макроопределения. Имя макрокоманды - INIT1,
хотя здесь возможны другие правильные уникальные ассемблерные имена.
Директива ENDM завершает макроопределение. Семь команд между директивами
MACRO и ENDM составляют тело макроопределения.
Имена, на которые имеются ссылки в макроопределении, CSEG, DSEG и
STACK должны быть определены где-нибудь в другом месте программы.
Макрокоманда INIT1 может использоваться в кодовом сегменте там, где
необходимо инициализировать регистры. Когда ассемблер анализирует команду
INIT1, он сначала просматривает таблицу мнемокодов и, не обнаружив там
соответствующего элемента, проверяет макрокоманды. Так как программа
содержит определение макрокоманды INIT1 ассемблер подставляет тело
макроопределения, генерируя необходимые команды - макрорасширение.
Программа использует рассматриваемую макрокоманду только один раз, хотя
имеются другие макрокоманды, предназначенные на любое число применений и
для таких макрокоманд ассемблер генерирует одинаковые макрорасширения.
На рис.20.1 показана ассемблированная программа. В листинге
макрорасширения каждая команда, помеченная слева знаком плюс (+), является
результатом генерации макрокоманды. Кроме того, в макрорасширении
отсутствует директива ASSUME, так как она не генерирует объектный код.
В последующем разделе "Включение из библиотеки макроопределений
показана возможность каталогизации макрокоманд в библиотеке и
автоматическое включение их в любые программы.
__________________________________________________________________________
TITLE MACRO1 (EXE) Макрос для инициализации
; --------------------------------------------
INIT1 MACRO
ASSUME CS:CSEG,DS:DSEG,SS:STACK,ES:DSEG
PUSH DS
SUB AX,AX
PUSH AX
MOV AX,DSEG
MOV DS,AX
MOV ES,AX
ENDM ;Конец макрокоманды
; --------------------------------------------
0000 STACK SEGMENT PARA STACK 'Stack'
0000 20 [ ???? ] DW 32 DUP(?)
0040 STACK ENDS
; --------------------------------------------
0000 DSEG SEGMENT PARA 'Data'
0000 54 65 73 74 20 6F MESSGE DB 'Test of macro-instruction', 13
66 20 6D 61 63 72
6F 2D 69 6E 73 74
72 65 73 74 69 6F
6E 0D
001A DSEG ENDS
; --------------------------------------------
0000 CSEG SEGMENT PARA 'Code'
0000 BEGIN PROC FAR
INIT1 ;Макрокоманда
0000 1E + PUSH DS
0001 2B C0 + SUB AX,AX
0003 50 + PUSH AX
0004 B8 ---- R + MOV AX,DSEG
0007 8E D8 + MOV DS,AX
0009 8E C0 + MOV ES,AX
000B B4 40 MOV AH,40H ;Вывод на экран
000D BB 0001 MOV BX,01 ;Номер
0010 B9 001A MOV CX,26 ;Длина
0013 8D 16 0000 R LEA DX,MESSGE ;Сообщение
0017 CD 21 INT 21H
0019 CB RET
001A BEGIN ENDP
001A CSEG ENDS
END BEGIN
Macros:
N a m e Length
INIT1. . . . . . . . . . . . . . . . 0004
Segments and Groups:
N a m e Size Align Combine Class
CSEG . . . . . . . . . . . . . . . . 001A PARA NONE 'CODE'
DSEG . . . . . . . . . . . . . . . . 001A PARA NONE 'DATA'
STACK. . . . . . . . . . . . . . . . 0040 PARA STACK 'STACK'
Symbols:
N a m e Type Value Attr
BEGIN. . . . . . . . . . . . . . . . F PROC 0000 CSEG Length=001A
MESSAGE. . . . . . . . . . . . . . . L BYTE 0000 DSEG
__________________________________________________________________________
Рис.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
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.
Формальный параметр может иметь любое правильное ассемблерное имя
(включая имя регистра, например, CX), которое в процессе ассемблирования
будет заменено на параметр макрокоманды. Отсюда следует, что ассемблер не
распознает регистровые имена и имена, определенные в области данных, как
таковые. В одной макрокоманде может быть определено любое число формальных
параметров, разделенных запятыми, вплоть до 120 колонки в строке.
__________________________________________________________________________
TITLE MACRO2 (EXE) Использование параметров
; ----------------------------------------------
INIT2 MACRO CSNAME,DSNAME,SSNAME
ASSUME CS:CSNAME,DS:DSNAME
ASSUME SS:SSNAME,ES:DSNAME
PUSH DS
SUB AX,AX
PUSH AX