Create your own interrupt
DOS has left a few interrupts open for us to use if we would like, so let's grab one and point it at our code.
Once we have written the code for the interrupt, we can make a TSR to set the interrupt vector and then stay resident.
We write our code for the interrupt to do anything as long as we don't call another interrupt. We also can have the layout
like the other interrupts where there is a service number in AH. See the code for an example.
We use some similar code from Interrupt Vectors to find the first
unused interrupt. We will start with int 34h. On most machines, this interrupt is the first unused interrupt, while the ones
before are used for misc. things and we won't even bother them.
We then can set the interrupt vector to point to our code via the INT 21h service.
Then call service 31h of INT 21h to Terminate and Stay Resident.
Version: 1.01b
Author: Ben Lunt (Forever Young Software)
Date: 9 Nov 2009
Assembler: NBASM
; This is a small util. to show how to create your own
; interrupt.
;
; (version 1.00b - original release)
; (version 1.01b - syntax update for newer version of NBASM)
;
; OUTINT.ASM
; Forever Young Software
; Copyright 1984-2024
; All rights reserved
; Version 1.01b
.model tiny
.code
.186
org 100h
start: jmp short InstallIt
;*******************************************************************
;;;; our interrupt code and data goes here
.even ; lets align it on the next word boundary
OurStart: cli
push ds ; save data seg
push cs ; point ds to cs
pop ds
or ah,ah ; if ah = 0 then service 0
je short Service0
cmp ah,01 ; if ah = 1 then service 1
je short Service1
cmp ah,02 ; if ah = 2 then service 2
je short Service2
JustExit: pop ds ; else just return
sti
iret
; our service #0 (ah = 00h)
Service0: mov dx,00h ; do something simple for example
jmp short JustExit
; our service #1 (ah = 01h)
Service1: mov dx,01h ; do something simple for example
jmp short JustExit
; our service #2 (ah = 02h)
Service2: mov dx,02h ; do something simple for example
jmp short JustExit
; other services go here
OurEnd:
;;;; end of our interrupt code and data
;*******************************************************************
InstallIt: mov si,offset StartIt ; display start up string
call prtstring ;
xor bx,bx ; make es:bx point to 0000:00D0h
mov es,bx ;
mov bx,00D0h ;
mov cx,204 ; 256 interrupts (00-FF)(-34h)
MainLoop: mov si,es:[bx] ; get interrupt vector address
inc bx ; offset first (little endian)
inc bx ;
mov ax,es:[bx] ; segment second (little endian)
inc bx ;
inc bx ;
cmp ax,0F000h ; if segment => F000h then in ROM-BIOS
jae short NotIRET ; (if in BIOS then skip it)
push es ;
mov es,ax ; see if IRET
mov dl,es:[si] ;
pop es ;
cmp dl,0CFh ; is it IRET
je short FndOne ; if so, then not used
NotIRET: inc byte CIntVNum ; inc for next time
loop MainLoop ;
mov si,offset NoFndOneS ; didn't find one
call prtstring
jmp short DoneErr
FndOne: mov si,offset FndOneS
call prtstring
mov ax,bx
sub ax,04 ; backup to first of vector
call prthex
mov si,offset IntNumS
call prtstring
mov al,CIntVNum ; display current int number
call prthexs ;
mov dl,'h' ; print 'h'
mov ah,02 ;
int 21h ;
push cs
pop ds
mov al,CIntVNum ; vector to change
mov ah,25h
mov dx,offset cs:OurStart
int 21h
mov ah,62h ; get and free environment block
int 21h ;
mov es,bx ;
mov ax,es:[2Ch] ;
mov es,ax ;
mov ah,49h ;
int 21h ;
mov dx,offset cs:OurEnd ; offset of end of our code
shr dx,04 ; div by 16 (make it a paragraph #)
inc dx ; just in case
add dx,16 ; The PSP
mov ax,3100h ; service number and RC = 0
int 21h ; TSR service
DoneErr: mov ah,4Ch ; exit to DOS (no TSR)
int 21h ;
prtstring proc near uses ax dx si
ps1: mov dl,[si] ; Get character
inc si ; Point to next one
or dl,dl ; End of string?
jz short ps2 ; Yes, so exit
mov ah,02h ; Output a character
int 21h
jmp short ps1 ; Keep doing it
ps2: ret
prtstring endp
PrtHexs proc near uses ax bx dx cx
mov bx,offset Hex
push ax
shr al,04h
xlatb
mov dl,al
mov ah,02
int 21h
pop ax
and al,0Fh
xlatb
mov dl,al
mov ah,02
int 21h
ret
PrtHexs endp
PrtHex proc near uses ax bx cx dx
mov bx,offset Hex
mov cx,04h
HexLoop: push ax
mov al,ah
shr al,04h
xlatb
mov dl,al
mov ah,02
int 21h
pop ax
shl ax,04h
loop HexLoop
ret
PrtHex endp
CIntVNum db 34h ; starting with int 34h
StartIt db 13,10,'Interrupt Install Util Version 01.01b'
db 13,10,'Forever Young Software Copyright 1984-2023',13,10
db 13,10,' Finding unused Interrupt vector number... (starting with 34h)',13,10,0
NoFndOneS db 13,10,"****Didn't find an unused interrupt vector number***"
FndOneS db 13,10,' Found an unused interrupt at: 0000:',0
IntNumS db 13,10,' Interrupt number: ',0
Hex db '0123456789ABCDEF'
.end start