Assembler - язык неограниченных возможностей

         

Последовательный порт


Каждый компьютер обычно оборудован, по крайней мере, двумя последовательными портами, которые чаще всего используются для подключения мыши и модема, но также могут использоваться и для подключения других дополнительных устройств или соединения компьютеров между собой. Для работы с устройствами, подключенными к портам, такими как мышь, используются драйверы, которые общаются с последовательным портом непосредственно на уровне портов ввода-вывода и предоставляют программам некоторый набор функций более высокого уровня, так что прямая работа с последовательными портами оказывается необходимой только при написании таких драйверов, работе с нестандартными устройствами или с модемами.

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:


    000 — 19 200 бод (110 бод без FOSSIL)

    001 — 38 400 бод (150 бод без FOSSIL)

    010 — 300 бод

    011 — 600 бод

    100 — 1200 бод

    101 — 2400 бод

    110 — 4800 бод

    111 — 9600 бод


биты 4 – 3: четность (01 — четная, 11 — нечетная, 00 или 10 — нет)

бит 2: число стоп-бит (0 — один, 1 — два)

биты 1 – 0: длина слова (00 — 5, 01 — 6, 10 — 7, 11 — 8)

DX = номер порта (00h – 03h)
Вывод: АН = состояние порта


    бит 7: тайм-аут

    бит 6: буфер вывода пуст ( без FOSSIL: регистр сдвига передатчика пуст)

    бит 5: в буфере вывода есть место (без FOSSIL: регистр хранения передатчика пуст)

    бит 4: обнаружено состояние BREAK

    бит 3: ошибка синхронизации

    бит 2: ошибка четности

    бит 1: ошибка переполнения — данные потеряны

    бит 0: в буфере ввода есть данные


AL = состояние модема


    бит 7: обнаружена несущая (состояние линии DCD)

    бит 6: обнаружен звонок (состояние линии RI)

    бит 5: запрос для передачи (состояние линии DSR)

    бит 4: сброс для передачи (состояние линии CTS)

    бит 3: линия DCD изменила состояние

    бит 2: линия RI изменила состояние

    бит 1: линия DSR изменила состояние

    бит 0: линия CTS изменила состояние


<


/p> 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. Более эффективным оказывается подход, состоящий в перехвате прерываний от внешних устройств, о котором рассказано далее.


Содержание раздела