home bbs files messages ]

Forums before death by AOL, social media and spammers... "We can't have nice things"

   comp.lang.asm.x86      Ahh, the lost art of x86 assembly      4,675 messages   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]

   Message 4,628 of 4,675   
   Borax Man to Branimir Maksimovic   
   Re: Help with COM1 serial port interrupt   
   12 Nov 23 12:14:58   
   
   From: rotflol2@nospicedham.hotmail.com   
      
   On Sun, 12 Nov 2023 00:30:40 GMT   
   Branimir Maksimovic  wrote:   
      
   > You have to tell PIC and UART to trigger interrupt. Just out instructions, I   
   guess that now since there   
   > is internet, you can find info easilly. Last time I programmed that was   
   1994...   
      
   Yes, you will need to write an interrupt handler which gets called   
   when the interrupt is triggered.  I haven't done this for a serial   
   port, but an example of an interrupt handler I wrote using the PC   
   timer is below.  Its a bit more complex than it needs to be, because   
   it also makes sound through the PC speaker.   
      
   OurInt08 is the interrupt handler.   
      
   This section saves the old interrupts then sets the interrupt vector to point   
   to our handler.  This is just for demonstration purposes.   
      
   	cli ;Turn off interrupts!   
   	mov word ax, [es:08h*4]   
   	mov word [cs:OldInt8], ax   
   	mov word ax, [es:08h*4 + 2]   
   	mov word [cs:OldInt8+2], ax   
      
   	mov ax, OurInt08   
   	mov word [es:08h*4], ax   
   	mov ax,cs   
   	mov word [es:(08h*4)+2], ax   
      
   Then don't forget to restore the old hander...   
      
      
   	mov ax, word [cs:OldInt8]   
   	mov word [es:08h*4], ax   
   	mov word ax, word [cs:OldInt8+2]   
   	mov word [es:08h*4 + 2], ax   
      
      
   The full program is below and it will compile with FASM.   
      
      
   	; A working example of how to use an interrupt handler   
   	; in DOS.  This source file is for FASM.   
   	;   
      
   	FORMAT MZ   
   	; DOS 16-bit EXE format   
   	STACK 400h   
   	HEAP 0	; No extra heap required.   
   	ENTRY CODE:Init   
      
   	; Quick example of using interrupts and chaning the PIT   
   	; tick rate   
   	use16   
      
   	freq = 42940   
   	inputlen = 160   
      
   SEGMENT CODE USE16   
      
   Init:   
   	mov ax,DATA2   
   	mov ds,ax   
   	mov fs,ax	     ; Set FS to point to data segment.   
   			     ; DS will change during the program   
   			     ; but FS won't as DOS doesn't touch this.   
   	mov ax, oldscreen    ; Create far pointer.   
   	mov word [dptr],ax   
   	mov word [dptr+2],ds   
      
   	mov ah,09h   
   	mov dx,intro   
   	int 21h  ; Print introduction message.   
      
   	mov cx,inputlen ; Input length   
   	xor ax,ax   
   	mov ah,3fh   
   	mov bx,0   
   	mov dx,input  ; Where to store   
   	int 21h   
   	jc endp   
   	cmp ax,8   
   	jg inputerror  ; Anything more than 6 characters we reject   
      
   	mov bx, ax ; BX will store the offset as we go through the input data.   
   	cmp [bx+input-1],0ah ; If this is not the last character   
   			     ; It means we didn't fill all the input   
   			     ; and some may be lost.  Best to end with   
   			     ; an error.  Besides, if it was a valid   
   			     ; number, it would have been well over the   
   			     ; maximum number of stars we could handle.   
   	jne inputerror   
      
   	xor bx, bx  ; Start index at 0.   
   	sub ax, 2 ; We don't want the CR/LF duo at the end.   
   	mov cx, ax   ; CX will be used to compare the index   
   	; to determine whether we have reached the end of the user data   
   	; we want to convert.   
   	xor ax, ax ; Start tally at 0.   
   	mov si, 10   ; Multiply each number we get by 10, as we push it up   
   		    ; as a significant digit.   
   	mov di, input   
   .getnum:   
   	cmp byte [di+bx], '0'  ; If less than '0', its not a numeral.   
   	jl inputerror   
   	cmp byte [di+bx], '9'  ; If more than '9', its not a numeral.'   
   	jg inputerror   
   	sub byte [di+bx], 30h  ; Sub 30h to convert the ascii numeral   
   			       ; to the number   
   	mul si		       ; Multiply what we have added so far by 10   
   	push dx   
   	mov dl, byte [di+bx]   
   	add ax,dx	       ; And add the next digit   
   	pop dx   
   	inc bx   
   	cmp bx, cx	   
   	jl .getnum	      ; If more digits, go again.   
   	mov cx, ax   
   begindemo:	  	   
   	mov al, 0x36   
   	out 0x43, al	;tell the PIT which channel we're setting   
   	mov ax, cx   
   	out 0x40, al	;send low byte   
   	mov al, ah   
   	out 0x40, al	;send high byte   
   	xor dx,dx   
   	mov es,dx   
      
   	cli ;Turn off interrupts!   
   	mov word ax, [es:08h*4]   
   	mov word [cs:OldInt8], ax   
   	mov word ax, [es:08h*4 + 2]   
   	mov word [cs:OldInt8+2], ax   
      
   	mov ax, OurInt08   
   	mov word [es:08h*4], ax   
   	mov ax,cs   
   	mov word [es:(08h*4)+2], ax   
   	mov ax, 0B800h   
   	mov es,ax   
   	call savescreen   
   	; The interrupt may update the screen prior to us saving it.   
   	call soundon   
   	sti   
      
   inputloop:   
      
   	mov cx,inputlen ; Input name   
   	mov ax,3f00h	; Input call   
   	xor bx,bx	; From keyboard (stdin)   
   	mov dx,keybuff	; Save at keybuff   
   	int 21h   
   	cmp [fs:keybuff],'q'   
   	jne inputloop   
   	xor dx,dx   
   	mov es,dx   
   	call soundonoff   
      
   	mov es,dx   
   	cli   
   	mov ax, word [cs:OldInt8]   
   	mov word [es:08h*4], ax   
   	mov word ax, word [cs:OldInt8+2]   
   	mov word [es:08h*4 + 2], ax   
      
   	xor ax,ax   
   	out 0x43, al	;tell the PIT which channel we're setting   
   	out 0x40, al	;send low byte   
   	out 0x40, al	;send high byte   
      
   	call restorescreen   
      
   	mov ax,DATA3   
   	mov ds,ax   
   	mov ax,0b800h   
   	mov es,ax   
      
   	mov ah,09h   
   	mov dx,data3msg   
   	int 21h  ; Print introduction   
      
      
   	mov cx,800   
   	mov bx,1   
   loop55:   
   	mov byte [es:bx],2   
   	add bx,2   
   	dec cx   
   	jnz loop55   
   endp:   
   	mov ax,4c00h	 ; Send exit code to dos   
   	int 21h 	; Send command to DOS   
   	   
   soundon:   
   	push ax   
   	in al,61h	       ;-Bits D1-D0 of "port 61h" are unmasked   
   	or al,03h	      ; or masked !   
   	out 61h,al   
   	pop ax   
   	ret	   
   soundonoff:   
   	push ax   
   	in al,61h	       ;-Bits D1-D0 of "port 61h" are unmasked   
   	xor al,03h	       ; or masked !   
   	out 61h,al   
   	pop ax   
   	ret	   
      
   	   
   OurInt08:   
   	; This interrupt handler could be called in any context   
   	; so we cannot assume anything about the state of the registers   
   	; including the segment registers.  As we are calling for user input   
   	; this is likely to be called during DOS function 3F, and DOS   
   	; may very well have set DS and ES to different values.   
   	pusha   
   	pushf   
   	add word [fs:elapsed], tickrate   
   	jnc skipint   
      
   	cli   
   	mov al,0b6h   
   	mov dx, 043h   
   	out dx,al   
      
   	mov ax,[fs:elapsed]   
   	mov dx, 042h   
   	out dx,al   
   	mov al, ah   
   	out dx,al   
   	sti   
   	popf   
   	popa   
   	jmp far [cs:OldInt8]	       ; using INT 08H emulation   
   skipint:   
   	push 0b800h   
   	pop gs   
   	mov bx,(160*20)-2   
   loop1:   
   	inc word [gs:bx]   
   	sub bx,2   
   	jnc loop1   
   ll2:   
   	mov al,20h		; EOI code for PIC   
   	out 20h,al		; Send   
   	popf   
   	popa   
   	iret   
      
   savescreen:   
   	push ax   
   	mov cx,2000-2   
   	xor si,si   
   	les di, [dptr]   
   	cld   
   	push 0b800h   
   	pop ds   
      
   	rep movsw   
   	push ds   
   	pop es   
   	mov ax,DATA2   
   	mov ds,ax   
      
   	pop ax   
   	ret   
      
   restorescreen:   
   	cld   
   	push ds   
   	mov ax,DATA2   
   	mov ds,ax   
   	push 0b800h   
   	pop es   
   	push ax   
   	mov cx,2000-2   
   	lds si, [dptr]		; This is unnecessary, we don't need to store the pointer   
   	; But I wanted to use the lds and les commands as an example   
   	xor di,di   
   	rep movsw   
   	pop ax   
   	pop ds   
   	ret   
   inputerror:   
   	mov dx,invalid ;Tell user about invalid input   
   	mov ah,09h   
   	int 21h   
   	mov ah,10h   
   	int 16h   ; Wait for keypress   
   	jmp begindemo   
      
      
   	OldInt8 dd 0   
      
      
   SEGMENT DATA3 USE16   
   	data3msg db "Now we are at the next part of the demonstration."   
   	db 13,10,"I will change some text colours.",13,10,24h   
      
      
   SEGMENT DATA2 USE16   
   	invalid   db "Invalid input or number too high.  ",\   
   	"Using default number of stars.",0ah,0dh,\   
   	"Press any key.",0ah,0dh,24h   
      
   	numstars  dw	10000   
   	elapsed dw 0   
   	intro	db  "Interrupt handler demo, by Borax Man",13,10   
   	db "September, 2020",13,10   
      
   [continued in next message]   
      
   --- SoupGate-Win32 v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]


(c) 1994,  bbs@darkrealms.ca