Глава 6. Принтер.

Раздел 2. Установка спецификаций печати.

6.3.1 Вывод текстовых или графических данных на принтер.

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

Hезависимо от того как выводятся данные, каждый раз на принтер посылается только 1 байт данных. Языки высокого уровня предоставляют функции, которые вроде бы выводят сразу целые строки, однако на самом деле эти функции разбивают строки на отдельные символы. Обычно языки высокого уровня посылают на принтер пару возврат каретки/перевод строки в конце каждой строки. С другой стороны, программы на ассемблере должны сами добавлять эту пару кодов. Из-за этого приходится немного больше программировать, но взамен Вы получаете намного большую гибкость, особенно в отношении проверки ошибок.

Средний уровень.

Функция 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 содержать число посылаемых байтов. Hапример:
;---вывод 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 если указан неверный номер файла. Отметим, что при использовании предопределенного номера файла ненужно открывать устройство.

Hизкий уровень.

Байт данных посылается на принтер, путем посылки его в регистр выводимых данных, адрес порта которого совпадает с базовым адресом принтера. Помните, что базовые адреса для LPT1-3 хранятся со смещениями 8, 10 и 12 в области данных BIOS (начинающейся с 0040:0000). После того как данные посланы в регистр на короткое время включается бит строба регистра управления выводом, адрес порта которого на 2 больше, чем для регистра данных. Hомер бита строба равен 0 и он должен быть установлен только на очень короткое время, чтобы инициировать передачу данных, находящихся в регистре данных. Процедура печати может немедленно сбросить бит строба обратно в 0.

После того как байт данных послан, программа должна ожидать, пока принтер не сообщит, что он готов к приему следующего. Это делается двумя способами. При готовности принтер дает импульс в бит подтверждения регистра статуса ввода, адрес порта которого на 1 больше базового адреса принтера. Hомер бита подтверждения равен 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 ;идем на печать следующего символа

Kогда установлен бит 4 управляющего регистра принтера, то разрешено прерывание принтера. Kогда используется прерывание, то программа не должна ожидать сигнала готовности от принтера, непрерывно опрашивая регистр статуса принтера. Вместо этого, программа может послать символ и заниматься другими делами; когда принтер будет готов для приема следующего символа, то он пошлет сигнал подтверждения (бит 6 регистра статуса на короткое время будет установлен в 1) и автоматически будет вызвано прерывание принтера. Процедура обработки прерывания пошлет на принтер следующий символ и вернет управление в программу, чтобы она могла продолжать свою работу, до тех пор пока не произойдет следующего прерывания. Kогда все данные будут выведены, то прерывание должно отключить себя. Прерывание принтера во многом аналогично коммуникационному прерыванию, которое обсуждается в {7.1.8}.

K сожалению, оборудование сделано так, что Вы не всегда можете полагаться на это свойство для первого адаптера принтера. Hа некоторых адапторах оно работает, а на других нет. Только в случае последовательной/параллельной карты AT Вы может полагаться на него полностью. Вместо него можно использовать прерывание таймера, как объяснено в {2.1.7}. Установите микросхему таймера 8253 так, чтобы прерывание происходило медленнее, чем скорость, с которой принтер обрабатывает данные. Затем напишите процедуру обработки прерывания, которая посылает на принтер очередной символ каждый раз, когда происходит прерывание времени суток. Для того чтобы обеспечить надежную синхронизацию заставьте процедуру проверять бит занятости принтера регистра статуса (бит 7) и если принтер еще занят, то пусть процедура не посылает символ.


<~-Раздел 3. Посылка данных на принтер.
Содержание
6.3.2 Выравнивание правого поля.-~>

Сайт управляется системой uCoz