Пример 2. Используя ассемблер TASM, разработать программу передачи символьной строки в параллельный порт на низком уровне.
Решение. Возможный вариант алгоритма вывода строки в параллельный порт приведен на рис. 47. Для определенности выбран порт LPT1. Вывод в порт будет происходить посимвольно, поэтому строка должна заканчиваться специальным символом, отмечающим ее конец. Таким символом может быть символ с кодом ноль, т.е. строка будет нультерминированной.
Для вывода одного символа в порт необходимо вначале получить состояние статусного регистра SR и проверить самый старший бит (BUSY). Если он равен 0 (принтер занят), следует организовать цикл опроса регистра SR до достижения готовности принтера. При готовности принтера код выводимого символа передается в регистр данных DR. Затем необходимо последовательность стробирующих импульсов передать в самый младший разряд (STROBE) регистра управления CR.
Рис. 47. Алгоритм вывода строки в параллельный порт.
Пример программы вывода строки в параллельный порт приведен ниже.
DATA SEGMENT
; выводимая ASCII-строка
str DB 'Тест принтера', 0Dh, 0Ah, 0
; переменная для хранения базового адреса LPT1
LPT1 DW 0
DATA ENDS
STACK SEGMENT STACK
DB 128 DUP(?)
STACK ENDS
CODE SEGMENT
ASSUME CS: CODE, DS: DATA, SS: STACK, ES: DATA
MOV AX, DATA
MOV DS, AX ; устанавливаем регистр DS на сегмент данных
PUSH DX ; сохранение в стеке содержимого регистра DX
MOV AX, 40h
MOV ES, AX ; регистр ES указывает на область данных BIOS
MOV DX, ES:[08] ; помещаем в регистр DX базовый адрес порта LPT1
MOV LPT1, DX
MOV BX, OFFSET str ; помещаем в регистр BX смещение выводимой строки
POP DX ; восстановление в стеке содержимого регистра DX
loop1: ; цикл печати строки
MOV AH, DS:[BX] ; получаем очередной символ строки
CMP AH, 0h ; проверка конца строки
JE exit ; да, выходим
CALL OUTBYTE ; нет, печатаем очередной символ
INC BX ; переходим на следующий символ
JMP loop1 ; повторяем, пока не будет достигнут конец строки
exit:
MOV AX, 4c00h ; завершить программу с кодом возврата 0
INT 21h ; выполнение прерывания 21h
OUTBYTE PROC ; процедура вывода символа из AL на принтер
PUSH DX
loop2: ; цикл ожидания готовности принтера
MOV DX, LPT1
INC DX ; адрес регистра состояния LPT1+1
IN AL, DX ; чтение регистра состояния
TEST AL, 80h ; проверка сигнала BUSY («1» - принтер готов)
JZ loop2 ; если нет, то повтор опроса
DEC DX ; адрес регистра данных
MOV AL, AH
OUT DX, AL ; запись байта в регистр данных
INC DX
INC DX ; адрес регистра управления LPT1+2
IN AL, DX ; чтение регистра управления и формирование строба
AND AL, 11111110b ; бит 0 (STROBE):=0
OUT DX, AL ; запись в регистр управления
OR AL, 00000001b ; бит 0 (STROBE):=1
OUT DX, AL ; запись в регистр управления
AND AL, 11111110b ; бит 0 (STROBE):=0
OUT DX, AL ; запись в регистр управления
POP DX
RET
ENDP
CODE ENDS
END
В начале программы описан сегмент данных, содержащий выводимую ASCIIZ-строку и переменную LPT1 размером слово для хранения базового адреса порта LPT1. В сегменте кода вначале определяется базовый адрес порта LPT1, а затем выполняется цикл LOOP1 побайтного вывода строки, условие завершения для которого – текущий символ равен 0.
Вывод символа производится процедурой OUTBYTE. На момент вызова процедуры код выводимого символа должен находиться в регистре AL. В самой процедуре считывается регистр SR и проверяется его разряд BUSY. Если принтер занят, организуется цикл LOOP2, в котором повторяется опрос регистра SR до достижения готовности принтера. Затем в регистр DR записывается код символа, а последовательность стробирующих импульсов – в разряд STROBE регистра CR.
Пример 3. В решении задачи 2 цикл ожидания готовности принтера может продолжаться бесконечно долго, если по какой-либо причине он держит на линии сигнал BUSY. Для устранения «зависания» в цикле LOOP2 выполните привязку к таймеру для проверки времени ожидания и, в случае ожидания более чем на 15÷20 сек, выведите сообщение о неготовности принтера к работе. Кроме того, после определения базового адреса выполните проверку, не равен ли он 0 (признак отсутствия LPT порта).
Do'stlaringiz bilan baham: |