Справочник программиста на персональном компьютере фирмы IBM. Принтер - Вывод текстовых или графических данных на принтер. Часть 2
ОГЛАВЛЕНИЕ
Средний уровень.
Функция 0 прерывания 17H посылает один символ на принтер.
Поместите символ в AL, а номер принтера в DX. При возврате AH
будет содержать регистр статуса, который надо постоянно проверять
для обнаружения ошибок. В [6.1.3] объясняется как это делать. Для
вывода потока данных установите указатель на буфер, содержащий
данные, и напишите процедуру типа следующей:
;---вывод данных на LPT1
MOV CX,NUMBER_CHARS ;CX содержит число байт для вывода
MOV DX,0 ;выбираем LPT1
NEXT_CHAR: MOV AH,0 ;функция посылки символа на принтер
MOV AL,[BX] ;BX указывает на буфер данных
INT 17H ;посылаем символ
TEST AH,8 ;проверяем бит ошибки
JNZ PRNTR_ERROR ;на обработку ошибки
INC BX ;увеличиваем указатель
LOOP NEXT_CHAR ;выводим следующий символ
Стандартное прерывание MS DOS для вывода на принтер это функ-
ция 5 прерывания 21H. Просто поместите символ в DL и выполните
прерывание. Эта функция всегда выводит на LPT1 и у нее нет возв-
ращаемых регистров.
;---вывод данных на LPT1
MOV AH,5 ;номер функции
MOV DL,CHAR ;готовим печатаемый символ
INT 21H ;посылаем его на принтер
Другой способ вывода данных на принтер это функция 40H преры-
вания 21H. Это функция стандартного вывода, с использованием
метода дескриптора файлов для доступа к файлу или устройству
[5.3.0]. В данном случае эта функция использует специальный пре-
допределенный номер файла для принтера. Этот номер #4 и его надо
поместить в BX. Функция имеет доступ только к LPT1, поэтому для
вывода на другой принтер Вам надо поменять базовые адреса
[6.1.4]. DS:DX должны указывать на выводимые данные, а CX содер-
жать число посылаемых байтов. Например:
;---вывод 120 байтов данных на LPT1
MOV AH,40H ;номер функции
MOV BX,4 ;номер файла для принтера
MOV CX,120 ;число посылаемых байтов
LEA DX,PRTR_DATA ;DS:DX указывают на данные
INT 21H ;посылаем данные
JC PRTR_ERROR ;на обработку ошибки
При возврате установленный флаг переноса индицирует ошибку, при
этом AX будет содержать 5, если принтер не связан с машиной и 6 -
если указан неверный номер файла. Отметим, что при использовании
предопределенного номера файла ненужно открывать устройство.
Низкий уровень.
Байт данных посылается на принтер, путем посылки его в регистр
выводимых данных, адрес порта которого совпадает с базовым адре-
сом принтера. Помните, что базовые адреса для LPT1-3 хранятся со
смещениями 8, 10 и 12 в области данных BIOS (начинающейся с
0040:0000). После того как данные посланы в регистр на короткое
время включается бит строба регистра управления выводом, адрес
порта которого на 2 больше, чем для регистра данных. Номер бита
строба равен 0 и он должен быть установлен только на очень корот-
кое время, чтобы инициировать передачу данных, находящихся в
регистре данных. Процедура печати может немедленно сбросить бит
строба обратно в 0.
После того как байт данных послан, программа должна ожидать,
пока принтер не сообщит, что он готов к приему следующего. Это
делается двумя способами. При готовности принтер дает импульс в
бит подтверждения регистра статуса ввода, адрес порта которого на
1 больше базового адреса принтера. Номер бита подтверждения равен
6 и обычно он установлен в 1. Импульс подтверждения сбрасывает
этот бит в 0 на достаточно долгое время, чтобы программа на языке
ассемблера могла увидеть это, если она постоянно следит за ре-
гистром.
Другой способ узнать, что принтер готов к приему следующего
байта данных состоит в непрерывной проверке бита 7 регистра ста-
туса, который сбрасывается в 0, когда принтер занят и устанавли-
вается в 1, когда он готов принять данные. Если Вы пишите проце-
дуру печати низкого уровня, которая должна работать в интерпрети-
руемом Бейсике или другом очень медленном языке, то надо исполь-
зовать этот метод.
Следующий пример получает базовый адрес LPT1 из области данных
BIOS и затем выводит данные из буфера, на который указывает ре-
гистр BX. Программа постоянно проверяет регистр статуса на заня-
тость и одновременно проверяет бит 3, чтобы проверить наличие
ошибки на принтере.
;---подготовка
MOV AX,40H ;ES указывает на область данных BIOS
MOV ES,AX ;
MOV DX,ES:[8] ;базовый адрес LPT1 в DX
MOV BX,DATA_START ;BX указывает на буфер данных
;---посылаем символ
NEXTCHAR: MOV AL,[BX] ;помещаем символ в AL
OUT DX,AL ;посылаем символ
INC DX ;DX будет указывать на регистр
INC DX ;управления выводом
MOV AL,13 ;цепочка битов для импульса строба
OUT DX,AL ;посылаем сигнал строба
DEC AL ;нормальное ссотояние регистра
OUT DX,AL ;посылаем его
;---проверка на ошибку и ожидание готовности принтера
DEC DX ;DX указывает на регистр статуса
NOT_YET: IN AL,DX ;получаем байт статуса
TEST AL,8 ;ошибка?
JNZ PRTR_ERROR ;переход на обработку ошибки
TEST AL,80H ;принтер занят?
JZ NOT_YET ;если занят, то назад
INC BX ;увеличиваем указатель в буфере данных
DEC DX ;DX указывает на регистр данных
JMP NEXTCHAR ;идем на печать следующего символа
Когда установлен бит 4 управляющего регистра принтера, то
разрешено прерывание принтера. Когда используется прерывание, то
программа не должна ожидать сигнала готовности от принтера, неп-
рерывно опрашивая регистр статуса принтера. Вместо этого, прог-
рамма может послать символ и заниматься другими делами; когда
принтер будет готов для приема следующего символа, то он пошлет
сигнал подтверждения (бит 6 регистра статуса на короткое время
будет установлен в 1) и автоматически будет вызвано прерывание
принтера. Процедура обработки прерывания пошлет на принтер сле-
дующий символ и вернет управление в программу, чтобы она могла
продолжать свою работу, до тех пор пока не произойдет следующего
прерывания. Когда все данные будут выведены, то прерывание должно
отключить себя. Прерывание принтера во многом аналогично коммуни-
кационному прерыванию, которое обсуждается в [7.1.8].
К сожалению, оборудование сделано так, что Вы не всегда можете
полагаться на это свойство для первого адаптера принтера. На
некоторых адапторах оно работает, а на других нет. Только в слу-
чае последовательной/параллельной карты AT Вы может полагаться на
него полностью. Вместо него можно использовать прерывание тайме-
ра, как объяснено в [2.1.7]. Установите микросхему таймера 8253
так, чтобы прерывание происходило медленнее, чем скорость, с
которой принтер обрабатывает данные. Затем напишите процедуру
обработки прерывания, которая посылает на принтер очередной сим-
вол каждый раз, когда происходит прерывание времени суток. Для
того чтобы обеспечить надежную синхронизацию заставьте процедуру
проверять бит занятости принтера регистра статуса (бит 7) и если
принтер еще занят, то пусть процедура не посылает символ.