; -----------------------------------------------------
NAMEPAR LABEL BYTE ;Список параметров
MAXNLEN DB 20 ; максимальная длина имени
NAMELEN DB ? ; длина введенного имени
NAMEFLD DB 20 DUP(' ') ; введенное имя
;Строка заголовка:
HEADG DB 'List of Employee Names Page '
PAGECTR DB '01',0AH,0AH
FFEED DB 0CH ;Перевод страницы
LFEED DB 0AH ;Перевод строки
LINECTR DB 01
PROMPT DB 'Name? '
; -----------------------------------------------------
MAIN PROC NEAR
CALL Q10CLR ;Очистить экран
CALL M10PAGE ;Установка номера страницы
A2LOOP:
MOV DX,0000 ;Установить курсор в 00,00
CALL Q20CURS
CALL D10INPT ;Ввести имя
CALL Q10CLR
CMP NAMELEN,00 ;Имя введено?
JE A30 ; если нет - выйти,
CALL E10PRNT ; если да - подготовить
; печать
JMP A20LOOP
A30:
MOV CX,01 ;Конец работы:
LEA DX,FFEED ; один символ
CALL P10OUT ; для прогона страницы,
RET ; возврат в DOS
MAIN ENDP
; Ввод имени с клавиатуры:
; -----------------------
D10INPT PROC NEAR
MOV AH,40H ;Функция
MOV BX,01 ; вывода на экран
MOV CX,05 ; 5 символов
LEA DX,PROMPT
INT 21H ;Вызов DOS
MOV AH,0AH ;Функция ввода с клавиатуры
LEA DX,NAMEPAR
INT 21H ;Вызов DOS
RET
D10INPT ENDP
; Подготовка для печати:
; ----------------------
E10PRNT PROC NEAR
CMP LINECTR,60 ;Конец страницы?
JB E20 ; нет - обойти
CALL M10PAGE ; да - печатать заголовок
E20: MOV CH,00
MOV CL,NAMELEN ;Число символов в имени
LEA DX,NAMEFLD ;Адрес имени
CALL P10OUT ;Печатать имя
MOV CX,01 ;Один
LEA DX,LFEED ; перевод строки
CALL P10OUT
INC LINECTR ;Увеличить счетчик строк
E10PRNT ENDP
; Подпрограмма печати заголовка:
; -----------------------------
M10PAGE PROC NEAR
CMP WORD PTR PAGECTR,3130H ;Первая страница?
JE M30 ; да - обойти
MOV CX,01 ;
LEA DX,FFEED ; нет --
CALL P10OUT ; перевести страницу,
MOV LINECTR,03 ; установить счетчик строк
M30:
MOV CX,36 ;Длина заголовка
LEA DX,HEADG ;Адрес заголовка
M40:
CALL P10OUT
INC PAGECTR+1 ;Увеличить счетчик страниц
CMP PAGECTR+1,3AH ;Номер страницы = шест.xx3A?
JNE M50 ; нет - обойти,
MOV PAGECTR+1,30H ; да - перевести в ASCII
INC PAGECTR
M50: RET
M10PAGE ENDP
; Подпрограмма печати:
; -------------------
P10OUT PROC NEAR ;CX и DX установлены
MOV AH,40H ;Функция печати
MOV BX,04 ;Номер устройства
INT 21H ;Вызов DOS
RET
P10OUT ENDP
; Очистка экрана:
; --------------
Q10CLR PROC NEAR
MOV AX,0600H ;Функция прокрутки
MOV BH,60H ;Цвет (07 для ч/б)
MOV CX,0000 ;От 00,00
MOV DX,184FH ; до 24,79
INT 10H ;Вызов BIOS
RET
Q10CLR ENDP
; Установка курсора (строка/столбец):
; ----------------------------------
Q20CURS PROC NEAR ;DX уже установлен
MOV AH,02 ;Функция установки курсора
MOV BH,00 ;Страница № 0
INT 10H ;Вызов BIOS
RET
Q20CURS ENDP
CODESG ENDS
END BEGIN
__________________________________________________________________________
Рис.19.1. Постраничная печать с заголовком.
Программа, приведенная на рис.19.1, аналогична программе на рис.9.1,
за исключением того, что после ввода имен с клавиатуры выводит их не на
экран, а на печатающее устройство. Каждая напечатанная страница содержит
заголовок и через двойной интервал список введенных имен в следующем виде:
List of Employee Names Page 01
Clancy Alderson
Ianet Brown
David Christie
...
Программа подсчитывает число напечатанных строк и при достижении
конца страницы выполняет прогон до начала следующей страницы. В программе
имеются процедуры:
D10INPT Выдает на экран запрос и затем вводит имя с клавиатуры.
E10PRNT Выводит имя на печатающее устройство (длина имени берется из
вводного списка параметров); в конце страницы вызывает процедуру
M10PAGE.
M10PAGE Выполняет прогон на новую страницу, печатает заголовок,
сбрасывает счетчик строк и увеличивает счетчик страниц на
единицу.
P100UT Общая подпрограмма для непосредственного вывода на печатающее
устройство.
В начале выполнения необходимо напечатать заголовок, но не делать
перед этим перевод страницы. Поэтому процедура M10PAGE обходит перевод
страницы, если счетчик PAGECTR содержит 01 (начальное значение). Поле
PAGECTR определено как
PAGECTR DB '01'
В начале выполнения необходимо напечатать заголовок, но не делать
перед этим перевод страницы. Поэтому процедура M10PAGE обходит перевод
страницы, если счетчик PAGECTR содержит 01 (начальное значение). Поле
PAGECTR определено как
PAGECTR DB '01'
В результате будет сгенерировано число в ASCII-коде - шест.3031. Процедура
M10PAGE увеличивает счетчик PAGECTR на 1 так, что значение становится
последовательно 3032, 3033 и т.д. Эти значения корректны до 3039, далее
следует 303A, что будет распечатано, как двоеточие (:). Поэтому, если в
правом байте поля PAGECTR появляется шест.3A, то это значение заменяется
на шест.30, а к левому байту прибавляется единица. Таким образом шест.303A
перекодируется в шест.3130, т.е. в 10 в символьном представлении.
Проверка на конец страницы до (но не после) печати имени гарантирует,
что на последней странице будет напечатано по крайней мере одно имя под
заголовком.
ПЕЧАТЬ ASCII-ФАЙЛОВ И ТАБУЛЯЦИЯ
________________________________________________________________
Табуляция, обеспечиваемая, например, видеоадаптерами, заключается в
замене одного символа табуляции (код 09) несколькими пробелами при выводе
так, чтобы следующая позиция была кратна 8. Таким образом, стандартные
позиции табуляции являются 8, 16, 24 и т.д. Многие принтеры, однако,
игнорируют символы табуляции. Поэтому, такая программа, как DOS PRINT,
предназначенная для печати ASCII файлов (например ассемблерных исходных
текстов) проверяет каждый символ, посылаемый на принтер. И, если
обнаруживается символ табуляции, то программа выдает несколько пробелов до
позиции кратной 8.
Программа, приведенная на рис.19.2, выводит на экран запрос на ввод
имени файла и, затем, печатает содержимое указанного файла. Эта программа
в отличие от приведенной на рис.17.3 (вывод файлов на экран) осуществляет
замену выводимых символов табуляции на соответствующее число пробелов. В
результате символ табуляции в позициях от 0 до 7 приводит к переходу на
позицию 8, от 8 до 15 - на 16 и т.д. Команды, реализующие данную логику,
находятся в процедуре G10XFER после метки G60. Рассмотрим три примера
обработки символа табуляции:
Текущая позиция печати: 1 9 21
Двоичное значение: 00000001 00001001 00010101
Очистка трех правых битов: 00000000 00001000 00010000
Прибавление 8: 00001000 00010000 00011000
Новая позиция: 8 16 24
В программе организованы следующие процедуры:
С10PRMP Запрашивает ввод имени файла. Нажатие только клавиши Return
приводит к завершению работы программы.
E10OPEN Открывает дисковый файл по указанному имени.
G10XFER Контролирует конец сектора, конец файла, конец области вывода,
символы "перевод строки" и табуляции. Пересылает обычные символы
в область вывода.
P10PRNT Распечатывает выводную строку и очищает область вывода.
R10READ Считывает сектор из дискового файла.
Коды "возврат каретки", "перевод строки" и "прогон страницы"
действительны для любых принтеров. Можно модифицировать программу для
подсчета распечатываемых строк и выполнения прогона страницы (шест.OC) при
достижении, например, строки 62.
Некоторые пользователи предпочитают устанавливать символы "прогон
страницы" в ASCII файлах с помощью текстового редактора в конкретных
местах текста, например, в конце ассемблерных процедур. Кроме того, можно
изменить программу для функции 05 базовой версии DOS. Эта функция
выполняет вывод каждого символа непосредственно на принтер. Таким образом
можно исключить определение и использование области вывода.
__________________________________________________________________________
TITLE PRINASK (COM) Чтение и печать дисковых записей
CODESG SEGMENT PARA 'Code'
ASSUME CS:CODESG,DS:CODESG,SS:CODESG,ES:CODESG
ORG 100H
BEGIN JMP MAIN
; ---------------------------------------------------------
PATHPAR LABEL BYTE ;Список параметров для
MAXLEN DB 32 ; ввода
NAMELEN DB ? ; имени файла
FILENAM DB 32 DUP(' ')
SECTOR DB 512 DUP(' ') ;Область ввода для файла
DISAREA DB 120 DUP(' ') ;Область вывода
COUNT DW 00
ENDCDE DW 00
FFEED DB 0CH
HANDLE DW 0
OPENMSG DB '*** Open error ***'
PROMPT DB 'Name of file? '
; ----------------------------------------------------------
MAIN PROC NEAR ;Основная программа
CALL Q10SCR ;Очистить экран
CALL Q20CURS ;Установить курсор
A10LOOP:
MOV ENDCDE,00 ;Начальная установка
CALL C10PRMP ;Получить имя файла
CMP NAMELEN,00 ;Есть запрос?
JE A90 ; нет - выйти
CALL E10OPEN ;Открыть файл,
; установить DTA
CMP ENDCDE,00 ;Ошибка при открытии?
JNE A80 ; да - повторить запрос
CALL R10READ ;Прочитать первый сектор
CMP ENDCDE,00 ;Конец файла, нет данных?
JE A80 ; да - повторить запрос
CALL G10XPER ;Распечатать сектор
A80:
JMP A10LOOP
A90: RET
MAIN ENDP
; Подпрограмма запроса имени файла:
; --------------------------------
C10PRMP PROC NEAR
MOV AH,40H ;Функция вывода на экран
MOV BX,01
MOV CX,13
LEA DX,PROMPT
INT 21H
MOV AH,0AH ;Функция ввода с клавиатуры
LEA DX,PATHPAR
INT 21H
MOV BL,NAMELEN ;Записать
MOV BH,00 ; 00 в конец
MOV FILENAM[BX],0 ; имени файла
C90 RET
C10PRMP ENDP
; Открытие дискового файла: