вывода оператором PRINT# Вы должны предварительно открыть принтер
в точности так же как и файл, с помощью оператора OPEN "LPT1" AS
#1 или OPEN "LPT3" AS #2. Оператор LPRINT всегда адресуется к
LPT1, в то время как PRINT# может адресоваться к любому принтеру.
Пара возврат каретки/перевод строки автоматически добавляется
в конце любого оператора LPRINT или PRINT#, если только он не
завершается точкой с запятой. Для избежания ненужных переводов
строки не забывайте завершать посылки любых управляющих кодов
точкой с запятой. То же самое надо делать, если Вы хотите, чтобы
строки текста печатались подряд, прилегающие одна к другой. Одна-
ко имейте ввиду, что многие принтеры не начинают печатать до тех
пор, пока они не получат данные для целой строки. Это определяет-
ся либо символом возврат каретки, либо тем, что число переданных
символов достигло 80-ти (или другого числа). Hе забывайте послать
завершающий код возврата каретки, чтобы вытолкнуть последнюю
порцию символов из буфера принтера.
Принтер автоматически переходит на слдеующую строку по дости-
жению конца строки. По умолчанию размер строки принтера равен 80
символам, но у широких принтеров это значение может быть больше.
Строки, выводимые в режимах плотной печати или печати двойной
ширины, также меняют длину строки. Для изменения номера столбца,
по достижении которого головка принтера перейдет на следующую
строку, можно установить ширину принтера командой WIDTH "LPT1",n
- где n требуемый номер столбца. Kогда печатается строка, длина
которой больше или равна ширине принтера, то печатающая головка
переходит на следующую строку, что эквивалентно выполнению кодов
возврат каретки/перевод строки. Это означает, что в случае, когда
длина строки в точности равна ширине принтера, то будет сделано
два перевода строки, если эта строка завершается, как обычно,
парой возврат каретки/перевод строки.
При графической печати принтер обычно устанавливают на беско-
нечную ширину. Чтобы сделать это, надо подать команду установки
ширины, равной 255, WIDTH "LPT1",255. Если Вы забудете включить
эту команду, то при выводе длинных последовательностей графичес-
ких данных Бейсик будет вставлять пару возврат каретки/перевод
строки после каждых 80 байтов данных. Эти добавочные символы
будут включаться в общее число байтов данных для графической
печати, поэтому конец передаваемых данных будет просто опущен.
Один оператор LPRINT может содержать несколько элементов дан-
ных в различных видах. Информация может содержаться в самом опе-
раторе, как например в LPRINT "The rain in Spain", или на нее
можно ссылаться по имени переменной, как в случае X$ = "The rain
in Spain": LPRINT X$. Специальные символы могут включаться за
счет использования функции CHR$. Управляющие коды обычно посы-
лаются именно этим способом, например, LPRINT CHR$(10) посылает
на принтер управляющий код перевода строки. Чаще всего CHR$ ис-
пользуется при посылке кодов ASCII, которые нельзя ввести с кла-
виатуры. Любые из перечисленных типов данных могут быть объедине-
ны в одном операторе. Если Вы хотите, чтобы различные элементы
данных печатались подряд, то разделяйте их точкой с запятой; если
же Вы разделите их запятыми, то следующий элемент будет выводить-
ся со следующей позиции табуляции. Это говорит о том, что опера-
тор LPRINT форматирует печать в точности так же, как это делает
оператор PRINT при выводе на экран. Вот несколько примеров:
100 LPRINT S$;" and ";Y$ 'комбинация трех строк
110 LPRINT X, Y, Z 'вывод трех чисел
120 LPRINT "The total is "; X 'комбинация строки и числа
130 LPRINT "The ";CHR$(27);CHR$(45);CHR$(1);"real";
CHR$(27);CHR$(45);CHR$(0);" thing."
'подчеркивание среднего слова
Оператор PRINT# может использовать те же типы данных, что и
оператор LPRINT, и он также позволяет включать несколько элемен-
тов данных в один оператор и смешивать различные типы данных.
Точки с запятой и запятые действуют в нем аналогичным образом.
Вот примеры, эквивалентные вышеприведенным:
100 OPEN "LPT1:" AS #2
110 PRINT #2,S$;" and ";Y$
120 PRINT #2,X, Y, Z
130 PRINT #2,"The total is "; X
140 PRINT #2,"The ";CHR$(27);CHR$(45);CHR$(1);"real";
CHR$(27);CHR$(45);CHR$(0);" thing."
Средний уровень.
Функция 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) и если
принтер еще занят, то пусть процедура не посылает символ.
6.3.2 Выравнивание правого поля.
Реальное выравнивание правого поля заключается в распределении
пробелов, находящихся в конце строки, равномерно по промежуткам
между словами. Hекоторые принтеры имеют специальный режим, кото-