3385
.pdf- 07: функция управления режимом заполнения массива: циклическое заполнение или однократное. Для переключения обработчика в режим циклического (однократного) заполнения массива необходимо поместить в регистр AL число 00h (01h), в регистр AH 07h (седьмая функция) и вызвать программное прерывание 60h. Для того, чтобы повторно заполнить массив в режиме однократного заполнения нужно воспользоваться функцией 06. Драйвер предназначен для работы с операционной системой MS-DOS на ЭВМ с процессорами типа х.386 и выше.
Вразделе 4.3.4 приведѐн листинг драйвера, работающего с портом LPT1
ипрерыванием IRQ7. Как видно, можно без труда унифицировать драйвер под данные порты.
4.3.3. Описание принципов сопряжения драйвера и графической оболочки
Пример графической оболочки приведѐн в разделе 4.3.4.. Программа написана на языке высокого уровня Turbo Pascal 7.0. Данная программа содержит подпрограммы связи с драйвером в виде ассемблерных вставок и построитель графиков. Алгоритм функционирования данной программы заключается в поэлементном изъятии байтов данных с помощью прерываний и построение соответствующих точек на графике. В данном случае применена линейная аппроксимация. Команда на обновление массива данных подаѐтся по сигналу с клавиатуры.
4.3.4. Программные средства ВИК
Листинг программы-драйвера (для порта LPT1)
;Степаненко Ю.А. 20.04.2001 ;Программирование параллельного порта LPT1 ;в режиме прерываний
.386 |
;Команды новых процессоров |
|
code segment use16 |
;16-разрядное приложение |
|
assume cs:code, ds:code |
;данные в сегменте команд |
|
org 100h |
;место под префикс |
|
main proc |
|
|
push cs |
;настроим DS |
|
pop ds |
;на сегмент команд |
|
;Замаскируем принтерное прерывание IRQ7 порта LPT1 |
||
in al,0021h |
;порт ведущего контроллера |
|
mov maska,al |
;сохраним |
|
or al,10000000b |
;замаскируем прерывание |
|
out dx,al |
;запишем |
;Сохраним байт управления портом
mov dx,37Ah |
;Адрес порта управления |
in al,dx |
|
mov b_ypr,al |
;сохранить в памяти |
;Сохраним обработчик прерываний параллельного порта LPT1 |
|
mov ax,350Fh |
;Функция 35h, вектор 0Fh |
int 21h
mov word ptr old_0F,bx ;Сохраним смещение mov word ptr old_0F+2,es;Сохраним сегмент
;Сохраним обработчик прерываний пользователя
mov al,60h |
;Функция 35 вектор 60h |
int 21h |
|
mov word ptr old_60,bx ;Сохраним смещение mov word ptr old_60+2,es;Сохраним сегмент
;Установим новый обработчик прерываний параллельного порта mov ax,250Fh ;Функция 25h, вектор 0Fh
mov dx,offset new_0F ;Адрес нового обработчика int 21h
;Установим новый обработчик прерываний пользователя
mov ax,2560h |
;Функция 25h, вектор 60h |
mov dx,offset new_60 |
;Адрес обработчика |
int 21h |
|
;Обработчик прерываний от порта LPT1 ;активизируется аппаратным IRQ7
;и программным прерыванием 0Fh new_0F proc
push ax |
;Сохраним все регистры |
push bx |
|
push dx |
|
push si |
|
push ds |
|
push cs |
;загрузим DS через стек |
pop ds |
|
mov dx,378h mov al,0Fh out dx,al
mov dx,379h
in al,dx |
;Прочитаем регистр состояния |
;где находится старший полубайт |
|
mov bh,al |
;Обработаем данные из порта: |
rol bx,2 |
;циклически сдвинем влево минуя CF |
bt bx,1 |
;перепишем в CF мл. бит |
rcr bx,1 |
;циклически сдвинем вправо через CF |
|
mov ah,bh |
|
;Поставим старший полубайт |
cicle: |
;Цикл ожидания появления |
|
in al,dx |
;младшего полубайта |
|
rol al,1 |
|
|
rol al,1 |
|
|
jb cicle |
;если ACK#<>0 повторить цикл |
|
ror al,1 |
|
|
ror al,1 |
|
|
mov bh,al |
;Обработаем данные из порта: |
|
rol bx,2 |
|
|
bt bx,1 |
|
|
rcr bx,1 |
|
|
ror bh,4 |
;Поставим на место младший полубайт |
|
and bh,00001111b;Формируем байт данных |
||
and ah,11110000b |
||
add ah,bh |
|
;данные в AH |
xor ah,01110111b;исправим инверсные биты |
||
mov bx,smeh |
;число заполненных элементов |
|
mov si,vxod |
;точка входа в массив |
|
mov dx,kol |
|
;размер массива |
mov [si][bx],ah;запишем в массив |
||
inc bx |
;прирастим |
|
cmp dx,bx |
|
;Сравним с размером массива |
ja perex |
;перейти если выше |
|
mov bx,0h |
|
;если переполнение - обнулим |
mov al,00h |
|
;Распознаем режим заполнения |
cmp al,regin |
;массива: останавливать заполнение |
|
je perex |
;или нет |
|
mov dx,37Ah |
;если останавливать - загрузим 0 |
|
out dx,al |
;в регистр управления портом |
perex:mov smeh,bx ;обновим smeh
mov dx,378h mov al,00h out dx,al
;восстановим регистры
pop ds pop si pop dx pop bx
mov al,20h ;Команда EOQ
out 20h,al |
;в контроллеры прерываний |
out 0A0h,al |
|
pop ax |
;восстановим регистры |
iret |
|
new_0F endp
;Функции управления (вход в AH,BX; выход в AX,DX)
new_60 proc |
|
push ds |
;Сохраним DS |
push cs |
;Настроим DS на данные |
pop ds |
|
cmp ah,00h |
;распознаем функцию управления |
je f_00 |
|
cmp ah,01h |
|
je f_01 |
|
cmp ah,02h |
|
je f_02 |
|
cmp ah,03h |
|
je f_03 |
|
cmp ah,05h je f_05 cmp ah,06h je f_06 cmp ah,07h je f_07
jmp near ptr outret
;00 :Функция передачи точки входа в массив данных ;выход :BX-сегмент, AX-смещение,DX-номер очередного ;регенерируемого элемента
f_00:
mov ax, vxod ;Передадим точку входа
push ds |
;в массив данных через AX |
pop bx |
;Сегмент массива в bx |
mov dx,smeh |
|
jmp near ptr outret |
|
;01 :Функция передачи элементов массива |
|
;при входе в BX-номер элемента i(0..N-4) |
|
;a[i+1]-AH,a[i]-AL,a[i+3]-DH,a[i+2]-DL, |
|
;BX-номер регенерируемого элемента |
|
f_01: |
|
push si |
|
mov si,vxod |
;Настроим SI на первый элемент |
mov ax,[si][bx];Запишем элементы массива в AX mov dx,[si][bx+2]
mov bx,smeh pop si
jmp near ptr outret
;02 :Функция запрещения аппаратного прерывания ;от порта LPT1
f_02: push ax push dx
;Настроим бит ACK# порта LPT1 на отмену прерываний
mov dx,37Ah |
;Адрес порта управления |
mov al,00000000b |
|
out dx,al |
;сбросим бит |
pop dx |
|
pop ax
jmp near ptr outret
;03 :Функция передачи элемента массива ;при входе в BX-номер элемента i(0..N-1) ;a[i]-AH
f_03: push si
mov si,vxod mov ah,[si][bx] pop si
jmp near ptr outret
;04 :Функция настройки резидентной программы f_04:
jmp near ptr outret
;05 :Функция завершения программы чтения данных ;из порта LPT1
f_05:
;Замаскируем принтерное прерывание
mov al,maska |
;загрузим |
|
or al,10000000b |
;модифицируем |
|
out 0021h,al |
|
;запишем |
;Восстановим исходный обработчик порта LPT1 |
||
push ds |
;Сохраним DS |
|
mov ax,250Fh |
;Функция 25h,вектор 0Fh |
lds dx,old_0F ;Сохраненный адрес int 21h
pop ds
;Восстановим исходный обработчик пользователя
push ds |
|
mov al,60h |
;Функция 25h,вектор 60h |
lds dx,old_60 |
;Сохраненный адрес |
int 21h
pop ds ;Восстановим DS ;Восстановим регистр управления портом
mov dx,37Ah mov al,b_ypr out dx,al
;Инициализация порта LPT1
;mov ah,01h
;mov dx,01h ;int 17h
;Восстановим маску прерываний
mov al,maska |
;загрузим |
out 0021h,al |
;восстановим |
;Завершим программу mov ax,4C00h
int 21h
jmp near ptr outret
;06 :Функция разрешения аппаратного прерывания ;от порта LPT1
f_06: push ax push dx
;Настроим бит ACK# порта LPT1 на разрешение прерываний
mov dx,37Ah |
;Адрес порта управления |
mov al,00010000b |
|
out dx,al |
;установим бит |
pop dx pop ax
jmp near ptr outret
;07 :Функция управления режимом заполнения массива ;Вход: AL-режим заполнения массива
;AL=00-циклическая регенерация
;AL=01-однократная регенерация с последующим
;запрещением аппаратного прерывания
;от сигнала ACK#
f_07:
mov regin,al
jmp near ptr outret
outret: pop ds iret
new_60 endp
old_0D dd 0 ;Ячейка для исходного вектора old_60 dd 0
mas db 1000 dup (0);Массив накопленных данных kol dw ($-mas) ;Размер массива
smeh dw 0 ;Число заполненных элементов maska db 0 ;Старая маска прерываний b_ypr db 0 ;Регистр управления порта vxod dw offset mas;Адрес первого элемента
regin db 0 ;Задает режим регенерации массива ressize=($-offset main);Размер программы без префикса code ends
end main
Содержание *.bat-файла для трансляции данного файла в .com программу:
C:\TASM\BIN\tasm /z/zi/n/m2 y_dr1,y_dr1,y_dr1 C:\TASM\BIN\tlink /x/v/3/t y_dr1,y_dr1
rem C:\TASM\BIN\td y_dr1
Листинг программы-драйвера (для порта LPT2)
;Степаненко Ю.А. 15.04.2001 ;Программирование параллельного порта LPT2
;в режиме прерываний |
|
|
.386 |
;Команды новых процессоров |
|
code segment use16 |
;16-разрядное приложение |
|
assume cs:code, ds:code |
;данные в сегменте команд |
|
org 100h |
;место под префикс |
|
main proc |
|
|
push cs |
;настроим DS |
|
pop ds |
;на сегмент команд |
|
;Замаскируем принтерное прерывание IRQ5 порта LPT2 |
||
in al,0021h |
;порт ведущего контроллера |
|
mov maska,al |
;сохраним |
|
or al,00100000b |
;замаскируем прерывание |
|
out dx,al |
;запишем |
|
;Сохраним байт управления портом |
||
mov dx,27Ah |
;Адрес порта управления |
|
in al,dx |
|
|
mov b_ypr,al |
;сохранить в памяти |
;Сохраним обработчик прерываний параллельного порта LPT2
mov ax,350Dh ;Функция 35h, вектор 0Dh int 21h
mov word ptr old_0D,bx ;Сохраним смещение mov word ptr old_0D+2,es;Сохраним сегмент
;Сохраним обработчик прерываний пользователя mov al,60h ;Функция 35 вектор 60h
int 21h
mov word ptr old_60,bx ;Сохраним смещение mov word ptr old_60+2,es;Сохраним сегмент
;Установим новый обработчик прерываний параллельного порта mov ax,250Dh ;Функция 25h, вектор 0Dh
mov dx,offset new_0D ;Адрес нового обработчика int 21h
;Установим новый обработчик прерываний пользователя
mov ax,2560h |
;Функция 25h, вектор 60h |
mov dx,offset new_60 ;Адрес обработчика |
|
int 21h |
|
;Размаскируем принтерное прерывание |
|
mov al,maska |
;загрузим |
and al,11011111b |
;модифицируем |
out 0021h,al |
;запишем |
mov ah,02h |
|
int 60h |
|
;Cделаем программу резидентной
mov dx,(ressize+10fh)/16 ;размер в параграфах
mov ax,3100h;Функция 'завершить и оставить в памяти' int 21h
main endp
;Размаскируем принтерное прерывание
mov al,maska |
;загрузим |
and al,11011111b |
;модифицируем |
out 0021h,al |
;запишем |
mov ah,02h |
|
int 60h |
|
;Cделаем программу резидентной
mov dx,(ressize+10fh)/16 ;размер в параграфах
mov ax,3100h;Функция 'завершить и оставить в памяти' int 21h
main endp |
|
in al,dx |
;Прочитаем регистр состояния |
;где находится старший полубайт |
|
mov bh,al |
;Обработаем данные из порта: |
rol bx,2 |
;циклически сдвинем влево минуя CF |
bt bx,1 |
;перепишем в CF мл. бит |
rcr bx,1 |
|
;циклически сдвинем вправо через CF |
|
mov ah,bh |
|
|
;Поставим старший полубайт |
cicle: |
;Цикл ожидания появления |
||
in al,dx |
|
;младшего полубайта |
|
rol al,1 |
|
|
|
rol al,1 |
|
|
|
jb cicle |
;если ACK#<>0 повторить цикл |
||
ror al,1 |
|
|
|
ror al,1 |
|
|
|
mov bh,al |
|
|
;Обработаем данные из порта: |
rol bx,2 |
|
|
|
bt bx,1 |
|
|
|
rcr bx,1 |
|
|
|
ror bh,4 |
|
;Поставим на место младший полубайт |
|
and bh,00001111b;Формируем байт данных |
|||
and ah,11110000b |
|||
add ah,bh |
|
|
;данные в AH |
xor ah,01110111b;исправим инверсные биты |
|||
mov bx,smeh |
;число заполненных элементов |
||
mov si,vxod |
|
;точка входа в массив |
|
mov dx,kol |
|
|
;размер массива |
mov [si][bx],ah;запишем в массив |
|||
inc bx |
|
;прирастим |
|
cmp dx,bx |
|
|
;Сравним с размером массива |
ja perex |
|
;перейти если выше |
|
mov bx,0h |
|
|
;если переполнение - обнулим |
mov al,00h |
|
|
;Распознаем режим заполнения |
cmp al,regin |
;массива: останавливать заполнение |
||
je perex |
|
;или нет |
|
mov dx,27Ah |
;если останавливать - загрузим 0 |
||
out dx,al |
|
;в регистр управления портом |
|
perex:mov smeh,bx ;обновим smeh |
|||
;восстановим регистры |
|||
pop ds |
|
|
|
pop si |
|
|
|
pop dx |
|
|
|
pop bx |
|
|
|
mov al,20h |
|
;Команда EOQ |
|
out 20h,al |
|
|
;в контроллеры прерываний |
out 0A0h,al |
|
|
|
pop ax |
|
;восстановим регистры |
|
iret |
|
|
|
new_0D endp
;Функции управления (вход в AH,BX; выход в AX,DX)
new_60 proc |
|
push ds |
;Сохраним DS |
push cs |
;Настроим DS на данные |
pop ds |
|
cmp ah,00h |
;распознаем функцию управления |
je f_00 |
|
cmp ah,01h |
|
je f_01 |
|
cmp ah,02h |
|
je f_02 |
|
cmp ah,03h |
|
je f_03 |
|
cmp ah,05h |
|
je f_05 |
|
cmp ah,06h |
|
je f_06 |
|
cmp ah,07h |
|
je f_07
jmp near ptr outret
;00 :Функция передачи точки входа в массив данных ;выход :BX-сегмент, AX-смещение,DX-номер очередного ;регенерируемого элемента
f_00:
mov ax, vxod |
;Передадим точку входа |
push ds |
;в массив данных через AX |
pop bx |
;Сегмент массива в bx |
mov dx,smeh |
jmp near ptr outret
;01 :Функция передачи элементов массива ;при входе в BX-номер элемента i(0..N-4) ;a[i+1]-AH,a[i]-AL,a[i+3]-DH,a[i+2]-DL, ;BX-номер регенерируемого элемента f_01:
push si
mov si,vxod ;Настроим SI на первый элемент mov ax,[si][bx];Запишем элементы массива в AX mov dx,[si][bx+2]
mov bx,smeh pop si
jmp near ptr outret
;02 :Функция запрещения аппаратного прерывания ;от порта LPT2