Помоему Вы всё очень усложняете со своими функциями. Не надо универсальных, надо под конкретную задачу (но самому понимать принцип работы СОМ порта). Практика показывает что С3.1 очень неоптимально компилирует код.
;--------------------------------------------------------------------
; можно подключить к проекту UltraLogik в виде функционального блока.
;
; (C) Copyright 2010 by Vel
;--------------------------------------------------------------------
public Start_COM1, Ini_COM1
DGROUP group DATA
DATA segment byte public 'DATA'
assume ds:DGROUP
Star_INT_0Ch dd 0 ; Адрес старого обработчика перывания 0Ch
Start_Data db 0 ; Переменная для контроля начала передачи
db 0
Shet_Size_Data dw 0 ; счетчик передаваемых данных
Byffer_Peredahi db ; начало буффера для передачи символов (1E - кирилица)
dd 0 ;+4 байта
dd 0 ;+4 байта
dd 0 ;+4 байта
dd 0 ;+4 байта
DATA ends
SYSTEM segment byte public 'CODE'
assume cs:SYSTEM, ds:DGROUP
;--------------------------------------------------------------------
;;;; < Обработчик прерывания СОМ 1 > ;;;;
;--------------------------------------------------------------------
New_INT_0Ch: ; Начало нового обработчика прерывания (0Ch)
; (INT 0Ch) - прерывание последовательного порта СОМ1
; вызывается, если порт СОМ1 получил данные.
push ax ; Сохранить ax в стек
push ds ; Сохранить ds в стек
push dx ; Сохранить dx в стек
push bx ; Сохранить bx в стек
Indet_INT:
;;;;;;{идентификация прерывания}
mov dx, 3FAh ; Адресс порта в dx (03FAh для чтения) - регистр
in al, dx ; Считать данные из порта 03FAh в al
and al, 07h ; Логическое И, обнуление 3-7 бит (00000111b)
cmp al, 2 ; Сравнение al с 2 (00000010b)-буфер передачи пуст. Сбрасывается после записи в 03F8h
je Vix_INT ; если равно, то на Vix_INT (прерывание по завершению передачи символа)
;;;;;;{сброс остальных прерываний}
; ---------------------------------------------------------------------------
;(сброс - пришли данные)
mov dx, 03F8h ; Адресс регистра передачи данных в dx
in al, dx ; Считать данные из порта 03F8h в al
jmp short $+2
;(сброс - состояние BREAK или ошибка)
mov dx, 03FDh ; Адресс регистра состояние break или ошибка в dx
in al, dx ; сбрасываем прерывание чтением из рег. состояния линии
jmp short $+2 ; задержка
;(сброс - изменилось состояние модема)
mov dx, 03FEh ; Адресс регистра состояния линии в dx
in al, dx ; сбрасываем прерывание чтением из регистра
jmp short $+2
jmp Exit_Indet_INT ; на выход
; ---------------------------------------------------------------------------
Vix_INT: ; прерывание по завершению передачи символа
;;;;;;{передача символа}
mov bx, Shet_Size_Data ; получаем значение счетчика
cmp bx, 16 ; сравнение
jge Exit_Indet_INT ; если больше или равно, то на метку, иначе
inc Shet_Size_Data ; инкремент, увеличиваем на 1
mov al, byte ptr Byffer_Peredahi+bx ; считываем значение из буффера передачи
mov dx, 03F8h ; адрес порта
out dx, al ; пишем в порт
;===============================
Exit_Indet_INT: ; послать в контроллер прерывания - прерывание обработано
mov dx, 0FF22h
mov ax, 0Ch
out dx, ax
pop bx
pop dx
pop ds
pop ax
iret ; возвращение в основную программу
;=============================================================================
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Инициализация СОМ 1
Ini_COM1 proc pascal near
push ds ; сохранить ds в стек
push es ; сохранить es в стек
push bx ; сохранить bx в стек
push dx ; сохранить dx в стек
mov ax, 350Ch ; АН = 35h, AL = номер прерывания (0Ch)
; (INT 0Ch) - прерывание последовательного порта СОМ1
; вызывается, если порт СОМ1 получил данные.
int 21h ; функция DOS: определить адрес старого обработчика
; (ES:BX)
mov word ptr Star_INT_0Ch, bx ; В bx смещение
mov word ptr Star_INT_0Ch+2, es ; В es сегментный адресс
mov ax, cs ; В ax адресс сегмента из cs (cs:SYSTEM)
mov bx, ds ; сохраняем ds в bx
mov ds, ax ; Установить ds на :SYSTEM (ds:SYSTEM)
assume ds:SYSTEM
lea dx, New_INT_0Ch ; Вычисление эффективного адреса New_INT_0Ch
mov ax, 250Ch ; АН = 25h, AL = номер прерывания (0Ch)
; сегментный адрес в DS
; смещение в DX
int 21h ; функция DOS: установить новый обработчик прерывания (0Ch)
mov ds, bx ; Востановить ds:DGROUP из bx
assume ds:nothing
;;;;;;{запрещение прерывания}
mov dx, 0FF28h ; Адресс порта в dx
in ax, dx ; Считать данные из порта 0FF28h в ax
and al, 0EFh ; Логическое И, обнуление 4 бита (11101111b)
out dx, ax ; Записать данные (ax) в порт (dx - (0FF28h))
;;;;;;{сбрасываем регистр данных}
mov dx, 3F8h ; чтением из порта 03F8h
in al, dx ; Считать данные из порта 3F8h в al
jmp short $+2 ; задержка
;;;;;;{сбрасываем регистр состояния линии}
mov dx, 3FDh ; чтением из порта 3FDh
in al, dx ; Считать данные из порта 3FDh в al
; 03FDh (для чтения) - регистр состояния линии
jmp short $+2 ; задержка
;;;;;;{сбрасываем регистр состояния модема}
mov dx, 3FEh ; чтением из порта 3FDh
in al, dx ;
jmp short $+2 ; задержка
;;;;{режим ввода делителя}
mov dx, 3FBh ;
mov al, 80h ; 7: бит DLAB : 1 = порты 3F8h и 3F9h в режиме ввода делителя
out dx, al ;
jmp short $+2
;;;;;;(Запись в Регистр управления модемом)
mov al, 00001100b ; (0Ch) Запись в Регистр управления модемом
; 0: 1 = установить выход DTR
; 1: 1 = установить выход RTS
; 2: 1 = установить OUT1 (не используется)
; 3: 1 = установить OUT2 (разрешить прерывания от RS-232)
mov dx, 3FCh
out dx, al
jmp short $+2
;;;;;;{младший байт делителя}
mov dx, 3F8h
mov al, 06h ; скорость 19 200
; задаем делитель скорости (0006h - 19200)
out dx, al ;
jmp short $+2
;;;;;;{старший байт делителя}
mov dx, 3F9h ;
mov al, 0 ; Скорость 19 200
out dx, al ;
jmp short $+2
;;;;;;{буферизация FIFO}(отключаем)
mov al, 00000000b ; бит 0 : Разрешение использования буферизации при приеме и предаче
; бит 1 : Сброс приемного буфера FIFO
; бит 2 : Сброс буфера FIFO передатчика
; биты 6-7: Установка значения числа символов в приемном буфере FIFO для
; инициирования прерывания (FIFO Trigger Level)
; 00 - 1 бит
mov dx, 3FAh
out dx, al
jmp short $+2
;;;;;;{режим работы}
mov dx, 3FBh
mov al, 00000011b ; Режим работы
; 0-1: число битов данных : 11 = 8 бит
; 2 : число стоп-битов : 0 = 1 стоп бит
; 3-4: тип четности : X0 = нет
; 5 : постоянная четность: 0 = отмена постоянной четности
; 6 : : 1 = имитировать обрыв линии
; 7 : бит DLAB : 0 = порты 3F8h и 3F9h в обычном режиме
out dx, al
jmp short $+2
;;;;;;(Запись в Регистр управления прерываниями)
mov al, 00000010b ; (5) Запись в Регистр управления прерываниями
; 0: прерывание по приему символа
; 1: прерывание по завершению передачи символа
; 2: прерывание по обрыву линии или ошибке в линии
; 3: прерывание по изменению состояния модема (любой из линий CTS, DSR, RI и DCD)
mov dx, 3F9h
out dx, al
jmp short $+2
pop dx ; восстановить dx основной программы
pop bx ; восстановить bx основной программы
pop es ; восстановить es основной программы
pop ds ; восстановить ds основной программы
retn
Ini_COM1 endp
;--------------------------------------------------------------------
; Подпрограмма Start_COM1 используется для передачи данных из буффера
; для передачи символов (16 байт) на дисплей
Start_COM1 proc pascal near
;===============================
Push dx ; сохраняем регистр bx
assume ds:DGROUP
;;;;;;{передача символа}
mov Shet_Size_Data, 0 ; записываем значение счетчика
mov al, 1Eh ; записываем (1E - кирилица для дисплея)
mov dx, 03F8h ; адрес порта
out dx, al ; пишем в порт
;===============================
pop dx ; востанавливаем регистр dx
ret ;все остальное додумает ассемблер (T320+)
Start_COM1 endp
SYSTEM ends
end