| [Назад] [Далее] | ![]() |
Каждый компьютер обычно оборудован, по крайней мере, двумя последовательными портами, которые чаще всего используются для подключения мыши и модема, но также могут использоваться и для подключения других дополнительных устройств или соединения компьютеров между собой. Для работы с устройствами, подключенными к портам, такими как мышь, используются драйверы, которые общаются с последовательным портом непосредственно на уровне портов ввода-вывода и предоставляют программам некоторый набор функций более высокого уровня, так что прямая работа с последовательными портами оказывается необходимой только при написании таких драйверов, работе с нестандартными устройствами или с модемами.
DOS всегда инициализирует первый порт СОМ1 как 2400 бод, 8N1 (8 бит в слове, 1 стоп-бит, четность не проверяется) и связывает с ним устройство STDAUX. В это устройство можно записывать и считывать один байт функциями 3 и 4.
Функция DOS 03h — Считать байт из STDAUX
| Ввод: | АН = 03h |
| Вывод: | AL = считанный байт |
Функция DOS 04h — Записать байт в STDAUX
| Ввод: | АН = 04h DL = байт |
Или же можно воспользоваться функциями записи в файл (40h) и чтения из файла (3Fh), поместив в ВХ число 3, как это было показано ранее для вывода на экран.
Хотя установленную DOS скорость работы порта (2400 бод) и можно изменить командой MODE, все равно отсутствие обработки ошибок, буферизации и гибкого управления состоянием порта делает эти функции DOS практически неприменимыми. BIOS позволяет управлять любым из портов, писать и читать один байт и считывать состояние порта с помощью функций прерывания 14h, но BIOS (так же как и DOS) не позволяет инициализировать порт на скорость выше, чем 9600 бод. Таким образом выясняется, что большинство программ вынуждено программировать порты напрямую, но, если в системе присутствует драйвер, предоставляющий набор сервисов FOSSIL (такие как Х00 или BNU), оказывается возможным пользоваться для полноценного буферированного обмена данными с последовательными портами только функциями прерывания 14h.
INT 14h АН = 04 — Инициализация FOSSIL-драйвера
| Ввод: | АН = 04h DX = номер порта (0 — для СОМ1, 1 — для COM2 и т.д.) |
| Вывод: | АХ = 1954h BL = максимальный поддерживаемый номер функции ВН = версия спецификации FOSSIL |
INT 14h АН = 05 — Деинициализация FOSSIL-драйвера
| Ввод: | АН = 05h DX = номер порта (00h – 03h) |
INT 14h АН = 00 — Инициализация последовательного порта
| Ввод: | АН = 00h AL = параметры инициализации: биты 7 – 5:
001 — 38 400 бод (150 бод без FOSSIL) 010 — 300 бод 011 — 600 бод 100 — 1200 бод 101 — 2400 бод 110 — 4800 бод 111 — 9600 бод бит 2: число стоп-бит (0 — один, 1 — два) биты 1 – 0: длина слова (00 — 5, 01 — 6, 10 — 7, 11 — 8) DX = номер порта (00h – 03h) |
| Вывод: | АН = состояние порта
бит 6: буфер вывода пуст (без FOSSIL: регистр сдвига передатчика пуст) бит 5: в буфере вывода есть место (без FOSSIL: регистр хранения передатчика пуст) бит 4: обнаружено состояние BREAK бит 3: ошибка синхронизации бит 2: ошибка четности бит 1: ошибка переполнения — данные потеряны бит 0: в буфере ввода есть данные
бит 6: обнаружен звонок (состояние линии RI) бит 5: запрос для передачи (состояние линии DSR) бит 4: сброс для передачи (состояние линии CTS) бит 3: линия DCD изменила состояние бит 2: линия RI изменила состояние бит 1: линия DSR изменила состояние бит 0: линия CTS изменила состояние |
INT 14h АН =01 — Запись символа в последовательный порт
| Ввод: | АН = 01h AL = символ DX = номер порта (00h – 03h) |
| Вывод: | АН = состояние порта |
INT 14h АН = 02 — Чтение символа из последовательного порта с ожиданием
| Ввод: | АН = 02h DX = номер порта |
| Вывод: | АН = состояние порта AL = считанный символ, если бит 7 АН равен нулю (не было тайм-аута) |
INT 14h AH = 03 — Получить текущее состояние порта
| Ввод: | АН = 03h DX = номер порта (00h – 03h) |
| Вывод: | АН = состояние линии AL = состояние модема |
Воспользуемся этими функциями, чтобы написать короткую терминальную программу:
; term.asm
; Простая терминальная программа для модема на COM2. Выход по Alt-X
;
.model tiny
.code
org 100h ; Начало СОМ-файла
start:
mov ah,0 ; инициализировать порт
mov al,11100011b ; 9600/8n1
mov dx,1 ; порт COM2
int 14h
main_loop:
mov ah,2
int 14h ; получить байт от модема,
test ah,ah ; если что-нибудь получено,
jnz no_input
int 29h ; вывести его на экран
no_input: ; иначе:
mov ah,1
int 16h ; проверить, была ли нажата клавиша,
jz main_loop ; если да:
mov ah,8
int 21h ; считать ее код (без отображения на экране),
test al,al ; если это нерасширенный ASCII-код,
jnz send_char ; перейти к посылке его в модем,
int 21h ; иначе - получить расширенный ASCII-код,
cmp al,2Dh ; если это Alt-X,
jne send_char
ret ; завершить программу
send_char:
mov ah, 1
int 14h ; послать введенный символ в модем
jmp short main_loop ; продолжить основной цикл
end start
Этот терминал тратит чрезмерно много процессорного времени на постоянные вызовы прерываний 14h и 16h. Более эффективным оказывается подход, состоящий в перехвате прерываний от внешних устройств, о котором рассказано далее.