⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 casyncms.asm

📁 tcpipstack源程序用于C51的TCP/IP协议栈,,C-C++,TCP/IP Stack
💻 ASM
字号:
;CASYNCMS.ASM - for Microsoft C
;Based on CASYNC.ASM by Curt Klinsing
;A set of C callable functions to support
;interrupt driven character I/O on the IBM PC. Input
;is buffered, output is polled.
;910609	rr	minor cleanup
;930811 rr	conversion for microsoft C
;931213	rr	fix various bugs (I hope)
;940529	rr	move to 9600

.286p
.seq

; ----- Equates -----------------------------------------------------

BASE		equ	03F8H	;BASE FOR SERIAL BOARD (COM1)
IER		equ	BASE+1	;Interrup Enable Register
LCR		equ	BASE+3	;Line control register
MCR		equ	BASE+4	;modem control register
LSR		equ	BASE+5	;line status register
MSR		equ	BASE+6	;modem status register

; Bits in IER
ERBFI		equ	01H	;enable 'data-ready' interrupt bit

; Bits in LSR
THRE		equ	20H	;8250 tbe flag

IntCtlr		equ	21H	;OCW 1 FOR 8259 CONTROLLER
EnblIRQ4	equ	0EFH	;Enable COMMUNICATIONS (IRQ4)
MaskIRQ4	equ	10H	;BIT TO DISABLE COMM INTERRUPT (IRQ4)

RS8259		equ	20H	;OCW 3 FOR 8259
RSTINT		equ	64H	;SPECIFIC EOI FOR COMM INTERRUPT

DosCall		equ	21h	;INTERRUPT NUMBER FOR DOS CALL

BUFSIZ		equ	512	;Max NUMBER OF CHARS (was 512)
SetIntVect	equ	25H	;SET INTERRUPT VECTOR FUNCTION NUMBER

;divisor is 48 for 2400 baud, 12 for 9600 baud,
;	96 for 1200 baud

BAUDRATEDIVISOR	equ	12

; ----- Data segment ------------------------------------------------

_DATA	SEGMENT	PARA PUBLIC 'DATA'

circ_buf	db	BUFSIZ DUP(?)	;ALLOW MaxIMUM BUFFERED CHARACTERS
buf_top		equ	$ - 1		;KEEP TRACK OF THE TOP OF THE BUFFER

circ_in		dw	offset circ_buf	;POINTER TO LAST CHAR. PLACED
					;IN BUFFER
circ_cur	dw	offset circ_buf	;POINTER TO NEXT CHAR. TO BE
					;RETRIEVED FROM BUFFER
circ_cnt	dw	0		;COUNT OF CHARACTERS USED IN BUFFER
_DATA	ENDS

; ----- Code segment ------------------------------------------------

_TEXT	SEGMENT PARA PUBLIC 'CODE'	
	ASSUME	CS: _TEXT, DS: _DATA

;int far inp_status( void )
;Returns the number of characters available in the input buffer.

	PUBLIC	_inp_status
_inp_status PROC FAR
	push	ds
	mov	ax,_DATA
	mov	ds,ax
	mov	ax,word ptr circ_cnt
	pop	ds
	ret
_inp_status ENDP

;void far inp_flush( void )
;Flush the input buffer.

	PUBLIC	_inp_flush
_inp_flush PROC FAR
	push	ds
	mov	ax,_DATA
	mov	ds,ax
	mov	bx,offset circ_buf
	mov	word ptr circ_in,bx
	mov	word ptr circ_cur,bx
	xor	ax,ax
	mov	word ptr circ_cnt,ax
	pop	ds
	ret
_inp_flush ENDP

;--------- Init -----------------------------------
;Program initialization:
;-- Set up vector for RS232 interrupt (0CH)
;-- Enbl IRQ4
;-- Enbl RS232 interrupt on data ready
;---------------------------------------------------
;void far init_comm( void )

	PUBLIC	_init_comm
_init_comm PROC FAR
	push	bp		;in case damaged by dos call
	cli			;disable interrupts

;---- Set up INT x'0C' for IRQ4 (COM1)

	push	ds		;save DS
	mov	ax,cs
	mov	ds,ax		;put CS into DS
	mov	dx,offset IntHdlr ;relative address of interrupt handler
	mov	al,0CH		;interrupt number for comm.
	mov	ah,SetIntVect	;function number for setting int vector
	int	DosCall		;set interrupt in 8086 table
	pop	ds		;restore DS

;---- Enbl IRQ4 on 8259 interrupt controller

	cli			;disable interrupts - again

	in	al,IntCtlr	;get current masks
	and	al,EnblIRQ4	;Reset IRQ4 mask
	out	IntCtlr,al	;And restore to IMR

;--- Set up 8250 port

	;divisor is 48 for 2400 baud, 12 for 9600 baud,
	;	96 for 1200 baud

	mov	dx,LCR
	mov	al,083h		;DLAB = 1
	out	dx,al		;to access baud rate divisors

	mov	dx,BASE
	mov	ax,BAUDRATEDIVISOR ;set baud rate divisor lsb
	out	dx,al
	inc	dx		;set baud rate divisor msb
	mov	al,ah
	out	dx,al

	mov	dx,LCR
	mov	al,03h		;8 bits, no parity, 1 stop
	out	dx,al

;---  Enbl 8250 data ready interrupt

	mov	dx,IER		;Interrupt Enbl Register
	mov	al,ERBFI	;Enable 'data-ready' interrupt
	out	dx,al

;---  Enbl OUT2 on 8250

	mov	dx,MCR		;modem control register
	mov	al,0BH		;Enable OUT2, DCD and DTR
	out	dx,al

	pop	bp
	sti			;enable interrupts
	ret
_init_comm ENDP

;void far uninit_comm( void )
;Removes the interrupt structure
;installed by init_comm(). Must be
;done before passing control to the DOS, else chars received
;will be stored into the next program loaded!

	PUBLIC	_uninit_comm	
_uninit_comm PROC FAR
	push bp

;--- Disable IRQ4 on 8259

	cli
	in	al,IntCtlr		;GET OCW1 FROM 8259
	or	al,MaskIRQ4		;DISABLE COMMUNICATIONS INTERRUPT
	out	IntCtlr,al

;--- Disable 8250 data ready interrupt

	mov	dx,LCR		;DX ==> LCR
	in	al,dx		;Reset DLAB for IER access
	and	al,7FH
	out	dx,al
	mov	dx,IER		;Interrupt Enbl Register
	mov	al,0		;Disable all 8250 interrupts
	out	dx,al

;---  Disable OUT2 on 8250

	mov	dx,MCR		;modem control register
	mov	al,0		;Disable OUT2
	out	dx,al

	sti			;reenable interrupts
	pop	bp
	ret
_uninit_comm ENDP

;int far inp_char( void )
;Return a character from the input
;buffer. Assumes you have called
;inp_status() to see if theres any characters to get.

	PUBLIC	_inp_char
_inp_char PROC FAR
	push	ds
	mov	ax,_DATA
	mov	ds,ax			;put _DATA in DS
	mov	bx,word ptr circ_cur
	xor	ax,ax
	mov	al,[bx]			;get next char from circ_buf
	dec	word ptr circ_cnt	;decrement circ_buf COUNT
	cmp	bx,offset buf_top
	jz	reset_cur		;JUMP IF SO
	inc	bx			;ELSE, BUMP PTR
	jmp	upd_cur
reset_cur:
	mov	bx,offset circ_buf	;RESET circ_cur TO BOTTOM OF BUF.
upd_cur:
	mov	word ptr circ_cur,bx	;SAVE NEW PTR
	pop	ds
	ret
_inp_char ENDP

;void far outp_char( int c )
;Output the character to the
;char c;serial port. This is not buffered
;or interrupt driven.

	PUBLIC	_outp_char
_outp_char PROC FAR
	push	bp
	mov	bp,sp
comout:
	mov	dx,LSR
	in	al,dx			;get 8250 status
	and	al,THRE			;check for transmitter ready
	jz	comout			;jump if not to wait
	mov	al,[bp+6]		;get char to al
	mov	dx,BASE			;data port
	out	dx,al			;output char to 8250
	pop	bp
	ret
_outp_char ENDP

; ----- RECEIVE INTERRUPT HANDLER -----------------------------------

	PUBLIC	IntHdlr
IntHdlr	PROC FAR	
	cli				;disable interrupts
	push	dx
	push	bx
	push	ax
	push	ds
	mov	ax,_DATA
	mov	ds,ax
	mov	bx,word ptr circ_in	;GET circ_buf IN PTR
	mov	dx,BASE			;GET DATA PORT NUMBER
	in	al,dx			;GET RECEIVED CHARACTER
	cmp	word ptr circ_cnt,BUFSIZ	;SEE IF circ_buf ALREADY FULL
	jz	clnup			;jump if so, discard char
savch:
	mov	[bx],al			;SAVE NEW CHARACTER IN circ_buf
	inc	word ptr circ_cnt	;BUMP circ_buf COUNT
	cmp	bx,offset buf_top	;ARE WE AT THE TOP OF THE circ_buf?
	jz	reset_in		;JUMP IF SO
	inc	bx			;ELSE, BUMP PTR
	jmp	into_buf
reset_in:
	mov	bx,offset circ_buf	;RESET circ_in TO BOTTOM OF BUF.
into_buf:
	mov	word ptr circ_in,bx	;SAVE NEW PTR
clnup:
	mov	al,RSTINT
	out	RS8259,al	;ISSUE SPECIFIC EOI FOR 8259
	pop	ds		;GET BACK ENTERING DS
	pop	ax
	pop	bx
	pop	dx
	sti
	iret
IntHdlr	ENDP

_TEXT ENDS

END

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -