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

📄 ser1.asm

📁 汇编编程艺术
💻 ASM
📖 第 1 页 / 共 2 页
字号:
		in	al, dx
		pop	dx
		ret
sl_GetMSRCom1	endp
;
;
; sl_SetMCRCom1-Writes the data in AL to the modem control register.
; sl_GetMCRCom1-Reads the data from the modem control register into AL.
;
; AL:
;	bit 0-	Data terminal ready (DTR)
;	bit 1-	Request to send (RTS)
;	bit 2-	Out 1
;	bit 3-	Out 2
;	bit 4-	Loop
;	bits 5-7 (must be zero)
;
		public	sl_SetMCRCom1
sl_SetMCRCom1	proc	far
		push	dx
		mov	dx, com1MCR
		out	dx, al
		pop	dx
		ret
sl_SetMCRCom1	endp
;
		public	sl_GetMCRCom1
sl_GetMCRCom1	proc	far
		push	dx
		mov	dx, com1MCR
		in	al, dx
		pop	dx
		ret
sl_GetMCRCom1	endp
;
;
;
; sl_GetLCRCom1- Reads the value from the line control register into AL.
; sl_SetLCRCom1- Writes the value in AL to the line control register.
;
; AL:
;	bits 0,1-	Word length selection
;	bit 2-		Number of stop bits
;	bit 3-		Parity Enable
;	bit 4-		Even parity select
;	bit 5-		Stuck parity
;	bit 6-		Set Break
;	bit 7-		Divisor latch access bit
;
		public	sl_GetLCRCom1
sl_GetLCRCom1	proc	far
		push	dx
		mov	dx, com1LCR
		in	al, dx
		pop	dx
		ret
sl_GetLCRCom1	endp
;
		public	sl_SetLCRCom1
sl_SetLCRCom1	proc	far
		push	dx
		mov	dx, com1LCR
		out	dx, al
		pop	dx
		ret
sl_SetLCRCom1	endp
;
;
; sl_GetIIRCom1-Reads the interrupt indentification register and returns its
;		value in AL.
;
; AL:
;	bit 0-		0 if interrupt pending, 1 if no interrupt.
;	bits 1,2-	Interrupt ID (highest priority).
;	bits 3-7-	Always zero.
;
; Interrupt ID
; bit 2  1	Source				Reset by
;     ----	-----------------------------	------------------------------
;     0  0	CTS, DSR, RI			Reading the MSR
;     0  1	Xmtr holding register empty	Reading IIR or writing to xmtr
;     1  0	Receiver data available		Reading rcvr buffer
;     1  1	Overrun, parity, framing, or	Reading the LSR.
;		break
;
;
		public	sl_GetIIRCom1
sl_GetIIRCom1	proc	far
		push	dx
		mov	dx, com1IIR
		in	al, dx
		pop	dx
		ret
sl_GetIIRCom1	endp
;
;
; sl_GetIERCom1-Reads the IER and returns it in AL.
; sl_SetIERCom1-Stores the value in AL into the IER.
;
; AL:
;	bit 0-	Enable data available interrupt.
;	bit 1-	Enable xmtr holding register empty interrupt.
;	bit 2-	Enable receive line status interrupt.
;	bit 3-	Enable modem status interrupt
;	bits 4-7  Always zero.
;
		public	sl_GetIERCom1
sl_GetIERCom1	proc	far
		push	dx
		call	sl_GetLCRCom1
		push	ax			;Save divisor access bit.
		and	al, 7fh			;Address the IER.
		call	sl_SetLCRCom1
		mov	dx, com1IER
		in	al, dx
		mov	dl, al			;Save for now
		pop	ax
		call	sl_SetLCRCom1		;Restore divisor latch
		mov	al, dl			;Restore IER value
		pop	dx
		ret
sl_GetIERCom1	endp
;
;
		public	sl_SetIERCom1
sl_SetIERCom1	proc	far
		push	dx
		push	ax
		mov	ah, al			;Save value to output
		call	sl_GetLCRCom1		;Get and save divsor access
		push	ax			;bit.
		and	al, 7fh			;Address the IER.
		call	sl_SetLCRCom1
		mov	al, ah
		mov	dx, com1IER
		out	dx, al
		pop	ax			;Restore divisor latch bit.
		call	sl_SetLCRCom1
		pop	ax
		pop	dx
		ret
sl_SetIERCom1	endp
;
;
;****************************************************************************
;
; Interrupt-driven Serial I/O
;
;
; sl_InitCom1Int-	Initializes the hardware to use interrupt-driven I/O
;			for COM1:
;
		public	sl_InitCom1Int
sl_InitCom1Int	proc	far
		pushf			;Save interrupt disable flag.
		push	es
		push	ax
		push	dx
;
; Turn off the interrupts while we're screwing around here.
;
		cli
;
; Save old interrupt vector.
;
		xor	ax, ax		;Point at interrupt vectors
		mov	es, ax
		mov	ax, Int0Cofs	;Get ofs int 0ch vector.
		mov	word ptr StdGrp:int0cVec, ax
		mov	ax, Int0Cseg	;Get seg int 0ch vector.
		mov	word ptr StdGrp:int0cVec+2, ax
;
; Point int 0ch vector at our interrupt service routine:
;
		mov	ax, cs
		mov	Int0Cseg, ax
		mov	ax, offset stdgrp:Com1IntISR
		mov	Int0Cofs, ax
;
; Clear any pending interrupts:
;
		call	far ptr sl_GetLSRCom1	;Clear Receiver line status
		call	far ptr sl_GetMSRCom1	;Clear CTS/DSR/RI Interrupts
		call	far ptr sl_GetIIRCom1	;Clear xmtr empty interrupt
		mov	dx, Com1Port
		in	al, dx			;Clear data available intr.
;
; Clear divisor latch access bit.  WHILE OPERATING IN INTERRUPT MODE, THE
; DIVISOR ACCESS LATCH BIT MUST ALWAYS BE ZERO.  If for some horrible reason
; you need to change the baud rate in the middle of a transmission (or while
; the interrupts are enabled) clear the interrupt flag, do your dirty work,
; clear the divisor latch bit, and finally restore interrupts.
;
		call	far ptr sl_getLCRCom1
		and	al, 7fh
		call	far ptr sl_SetLCRCom1
;
;
; Enable the receiver and transmitter interrupts
;
		mov	al, 3		;Enable rcv/xmit interrupts
		call	far ptr sl_SetIERCom1
;
; Must set the OUT2 line for interrupts to work.
; Also sets DTR and RTS active.
;
		mov	al, 00001011b
		call	far ptr sl_SetMCRCom1
;
; Activate the COM1 (int 0ch) bit in the 8259A interrupt controller chip.
;
		in	al, 21h
		mov	StdGrp:i8259a, al	;Save interrupt enable bit.
		and	al, 0efh	;Bit 4=IRQ 4 = INT 0Ch
		out	21h, al
;
		pop	dx
		pop	ax
		pop	es
		popf			;Restore interrupt disable flag.
		ret
sl_InitCom1Int	endp
;
;
; sl_IntsOffCom1- Disconnects the interrupt system and shuts off interrupt
;		  activity at the COM1: port.
;
;	Warning!  This routine assumes that interrupts are currently active
;		  due to a call to sl_InitCom1Int.  If you call this guy
;		  w/o first calling sl_InitCom1Int you will probably crash
;		  the system.  Furthermore, this routine makes the (rather
;		  presumptuous) assumption that no one else has patched into
;		  the INT 0Ch vector since SL_InitCom1Int was called.
;
		public	sl_IntsOffCom1
sl_IntsOffCom1	proc	far
		pushf
		push	es
		push	dx
		push	ax
;
		cli			;Don't allow interrupts while messing
		xor	ax, ax		; with the interrupt vectors.
		mov	es, ax		;Point at interrupt vectors.
;
; First, turn off the interrupt source:
;
		call	far ptr sl_GetMCRCom1
		and	al, 3			;Mask out OUT 2 bit (masks ints)
		call	far ptr sl_SetMCRCom1
;
		in	al, 21h			;Get 8259a ier
		and	al, 0efh		;Clear IRQ 4 bit.
		mov	ah, StdGrp:i8259a		;Get our saved value
		and	ah, 1000b		;Mask out com1: bit (IRQ 4).
		or	al, ah			;Put bit back in.
		out	21h, al
;
; Restore the interrupt vector:
;
		mov	ax, word ptr StdGrp:Int0cVec
		mov	Int0Cofs, ax
		mov	ax, word ptr StdGrp:Int0cVec+2
		mov	Int0Cseg, ax
;
		pop	ax
		pop	dx
		pop	es
		popf
		ret
sl_IntsOffCom1	endp
;
;----------------------------------------------------------------------------
;
; Com1IntISR- Interrupt service routine for COM1:
;
Com1IntISR	proc	far
		push	ax
		push	bx
		push	dx
TryAnother:	mov	dx, Com1IIR
		in	al, dx			;Get id
		test	al, 1			;Any interrupts left?
		jnz     IntRtn
		test	al, 100b
		jnz	ReadCom1
		test	al, 10b
		jnz	WriteCom1
;
; Bogus interrupt?
;
		call	sl_GetLSRCom1		;Clear receiver line status
		call	sl_GetMSRCom1		;Clear modem status.
		jmp	TryAnother
;
IntRtn:		mov	al, 20h			;Acknowledge interrupt to the
		out	20h, al			; 8259A interrupt controller.
		pop	dx
		pop	bx
		pop	ax
		iret
;
; Handle incoming data here:
; (Warning: This is a critical region.  Interrupts MUST BE OFF while executing
;  this code.  By default, interrupts are off in an ISR.  DO NOT TURN THEM ON
;  if you modify this code).
;
ReadCom1:	mov	dx, Com1Port
		in	al, dx			;Get the input char
		mov	bx, StdGrp:InHead
		mov	StdGrp:[bx], al
		inc	bx
		cmp	bx, offset stdgrp:InpBufEnd
		jb	NoInpWrap
		mov	bx, offset stdgrp:InpBuf
NoInpWrap:	cmp	bx, StdGrp:InTail
		je	TryAnother
		mov	StdGrp:InHead, bx
		jmp	TryAnother
;
;
; Handle outgoing data here (This is also a critical region):
;
WriteCom1:      mov	bx, StdGrp:OutTail
		cmp	bx, StdGrp:OutHead
		jne	OutputChar
;
; If head and tail are equal, simply set the TestBuffer variable to zero
; and quit.  If they are not equal, then there is data in the buffer and
; we should output the next character.
;
		mov	StdGrp:TestBuffer, 0
		jmp	TryAnother
;
; The buffer pointers are not equal, output the next character down here.
;
OutputChar:     mov	al, StdGrp:[bx]
		mov	dx, Com1Port
		out	dx, al
		inc	bx
		cmp	bx, offset stdgrp:OutBufEnd
		jb      NoOutWrap
		mov	bx, offset stdgrp:OutBuf
NoOutWrap:	mov	StdGrp:OutTail, bx
		jmp	TryAnother
Com1IntISR	endp
;
;
;----------------------------------------------------------------------------
;
; Routines to read/write characters in serial buffers.
;
		public	sl_InCom1
sl_InCom1	proc	far
		pushf				;Save interrupt flag
		push	bx
		sti				;Make sure interrupts are on.
TstInLoop:	mov	bx, StdGrp:InTail
		cmp	bx, StdGrp:InHead
		je	TstInLoop
		mov	al, StdGrp:[bx]		;Get next char.
		cli				;Turn off ints while adjusting
		inc	bx			; buffer pointers.
		cmp	bx, offset stdgrp:InpBufEnd
		jne	NoWrap2
		mov	bx, offset stdgrp:InpBuf
NoWrap2:	mov	StdGrp:InTail, bx
		pop	bx
		popf				;Restore interrupt flag.
		ret
sl_InCom1	endp
;
;
		public	sl_OutCom1
sl_OutCom1	proc	far
		pushf
		cli				;No interrupts now!
		cmp	StdGrp:TestBuffer, 0	;Write directly to serial chip?
		jnz	BufferItUp
		call	far ptr sl_WriteCom1	;Output to port
		mov	StdGrp:TestBuffer, 1	;Must buffer up next char.
		popf
		ret
;
BufferItUp:	push	bx
		mov	bx, StdGrp:OutHead
		mov	StdGrp:[bx], al
		inc	bx
		cmp	bx, offset stdgrp:OutBufEnd
		jne	NoWrap3
		mov	bx, offset stdgrp:OutBuf
NoWrap3:	cmp	bx, StdGrp:OutTail
		je	NoSetTail
		mov	StdGrp:OutHead, bx
NoSetTail:	pop	bx
		popf
		ret
sl_OutCom1	endp
;
stdlib		ends
		end

⌨️ 快捷键说明

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