[comp.sys.ibm.pc] Need help in my assembly routine.

law@janus.Berkeley.EDU (Katherina Law) (12/09/89)

Hi, netlanders,
I have just modified an assembly program from a book.  The program
is to define its own interrupt driver for the serial port controller,
reads data in and stuff it into the keyboard buffer.
The problem I have now is I couldn't get through the port enabling
part.  I have no problem with it in C.  Right now it just hungs
the system.  When I trace through it in debug, it will go as far as
to the "in" statement in asc_enb, but once that is executed and I cannot
quit out of debug, I'll get memory allocation error.  Please help,
right now I am just too blind to see anything I am doing?!

Many thanks in advance!!

The following is my program:

DOSSEG
.MODEL SMALL
low_mem SEGMENT AT 0000h
buffer_head	equ 41ah
buffer_tail	equ 41ch
low_mem ENDS

pic_mask	equ	21h	;port address, 8259 mask register
pic_eoi	equ	20h	;port address, 8259 EOI instr.
comm_data	equ	03f8h	;COM1
comm_ier	equ	03f9h
comm_lcr	equ	03fbh
comm_mcr	equ	03fch
comm_stat	equ	03fdh
com_int	equ	0ch
int_mask	equ	10h	;Mask for 8259, COM1 is IRQ4.
.CODE 
ORG 0h
intc_offs	dw	0	;original contents of Int 0Ch
intc_seg	dw	0	;service vector

ascenb	proc	far
	call	asc_enb	;enable interrupt
again:	mov	ah,01h	;check keyboard
	int	16h
	jz	again	;exit if key is pressed
	call	asc_dsb
	mov	ax,4c00h
	int	21h
ascenb	endp

asc_enb proc	near
	push	bx
	push	es
	mov	ah,35h	;get current address of asynch
	mov	al,com_int	;port's interrupt handler
	int	21h	;ES:BX = addr
	mov	intc_seg,es	;save segment
	mov	intc_offs,bx 	;save offset
	mov	dx,offset asc_int
	mov	ah,25h	;set address of new handler
	mov	al,com_int
	int	21h
	mov	dx,comm_lcr	;9600, 1 stop, 7 bits
	mov 	al,09ah
	out	dx,al
	mov	dx,comm_data
	mov	al,0ch
	out	dx,al
	mov	dx,comm_mcr
	mov	al,00h
	out	dx,al
	mov	dx,comm_mcr	;modem controller DTR & OUT2
	mov	al,0bh
	out	dx,al
	mov	dx,comm_lcr
	mov	al,01ah
	out	dx,al
	mov	dx,comm_ier	;interrupt enable register
	mov	al,1	;on asynch controller
	out	dx,al
	in	al,pic_mask	;read current 8259A int. mask.
	and	al,not int_mask	;reset mask for this COM port.
	out	pic_mask,al	;write back 8259A int. mask.
	pop	es
	pop	bx
	ret
asc_enb	endp

asc_int	proc	far	;interrupt service for asynch controller
	sti	;turn interrupts back on.
	push	ax	;save all registers.
	push	bx
	push	dx
	push	ds	;save and go to low mem
	mov	ax,cs
	mov	ds,ax
	mov	dx,comm_data
	in	al,dx	;read this character.
	mov	dl,al
	push	ds
	cli		;clear interrupts for pnter.
	mov	ax,low_mem
	mov	ds,ax	;get keyboard buffer addr
	mov	di,buffer_tail
	mov	bx,ds:[di]
	add	bx,400h
	mov	byte ptr [bx],dl	;put in keyboard buffer
	add	WORD PTR[di],2h
	cmp	WORD PTR[di],03eh
	jne	buffit
	mov	WORD PTR[di],01eh
buffit:	sti		;turn interrupts back on.
	pop	ds
	mov	al,20h	;send EOI to 8259A.
	out	pic_eoi,al
	pop	ds	;restore all registers
	pop	dx
	pop	bx
	pop	ax
	iret		;exit handler.
asc_int	endp

asc_dsb proc	near	;disable interrupt and release service vector
	in	al,pic_mask	;read current 8259A int. mask.
	or	al,int_mask	;set mask for this COM port.
	out	pic_mask,al	;write int. mask back to 8259A.
	push	ds
	mov	dx,intc_offs	;saved offset
	mov	ds,intc_seg	;saved segment
	mov	ah,25h	;restore address of original
	mov	al,com_int	;com port interrupt handler.
	int	21h
	pop	ds
	ret
asc_dsb	endp

END