How can i create my own hardware and software interrupt, what are the codes sent to hardware to access information/data please help with the codes;)

Recommended Answers

All 4 Replies

1.) You don't generate a hardware interrupt; the hardware does, when it wants to grab the processor's attention. For example, when you strike a key on the keyboard a type 9 interrupt is generated, and that causes the processor to drop what it's doing, and retrieve the keystroke from the keyboard controller.

2.) You generate a software interrupt by using the int instruction. Software interrupts are primarily a method of indirect addressing.

3.) Hardware programming revolves around the use of in and out instructions. For example, in order to retrieve the above mentioned keystroke you would use the instruction

in al, 60h

Which causes the processor to read a byte from port 60h (off of which hangs the keyboard controller). More generally, how you program a particular piece of hardware, and which hardware port(s) you need to read or write to in order to do so, you would need to discover from the hardware manufacturer. (Unless, like the address of the keyboard controller, it is something which has been carved in stone ever since the PC made its first appearance.)

Could you please Xplain to me the meaning of this code?
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.00b
Author: Ben Lunt (Forever Young Software(R))
Date: 8 Dec 1998
Assembler: NBASM 00.23.xx
; This is a small util. to show how to create your own
; interrupt.
;
; (version 1.00b - original release)
;
; OUTINT.ASM
; Forever Young Software
; Copyright 1997
; All rights reserved
; Version 1.00b
.model tiny
.186
org 100h
start: jmp short InstallIt
;*******************************************************************
;;;; our interrupt code and data goes here
.algnw ; 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.00b'
db 13,10,'Forever Young Software(r) (C)opyright 1984-2000',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

----------------------------------------------------------------------------
The first part is the interrupt service routine itself. It doesn't do anything very exciting; just loads a value into dx, and then returns.
----------------------------------------------------------------------------

.model tiny
.186
org 100h
start: jmp short InstallIt
;*******************************************************************
;;;; our interrupt code and data goes here
.algnw ; 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
;*******************************************************************
-------------------------------------------------------------------------------
The rest of the program ist the installation procedure
-------------------------------------------------------------------------------

-------------------------------------------------------------------------------
Prints one of the messages at the bottom
-------------------------------------------------------------------------------

InstallIt: mov si,offset StartIt ; display start up string
call prtstring ;

-------------------------------------------------------------------------------
point es:bx at the interrupt vector table
-------------------------------------------------------------------------------

xor bx,bx ; make es:bx point to 0000:00D0h
mov es,bx ;
mov bx,00D0h ;

-------------------------------------------------------------------------------
load cx with max number of entries you want to examine
-------------------------------------------------------------------------------

mov cx,204 ; 256 interrupts (00-FF)(-34h)

-------------------------------------------------------------------------------
look at the entries one at a time
-------------------------------------------------------------------------------

MainLoop:
-------------------------------------------------------------------------------
load ax:si with address of isr
-------------------------------------------------------------------------------
mov si,es:[bx] ; get interrupt vector address
inc bx ; offset first (little endian)
inc bx ;
mov ax,es:[bx] ; segment second (little endian)

------------------------------------------------------------------------------
point es:bx at next entry in table
-----------------------------------------------------------------------------
inc bx ;
inc bx ;

------------------------------------------------------------------------------
Does ax:si point to read only memory in the BIOS?
----------------------------------------------------------------------------- 
cmp ax,0F000h ; if segment => F000h then in ROM-BIOS
jae short NotIRET ; (if in BIOS then skip it)

-----------------------------------------------------------------------------
does routine pointed to by ax:si consist of nothing more than an iret
instruction (i.e. - available for use)?
-----------------------------------------------------------------------------
push es ;
mov es,ax ; see if IRET
mov dl,es:[si] ;
pop es ;
cmp dl,0CFh ; is it IRET

------------------------------------------------------------------------------
if available for use jump out of loop; otherwise go round loop,
and look at next entry in interrupt vector table
------------------------------------------------------------------------------

je short FndOne ; if so, then not used
NotIRET: inc byte CIntVNum ; inc for next time
loop MainLoop ;

-------------------------------------------------------------------------------
Gone round loop max number of times, and still haven't found free
entry in vector table? Then print error message and exit.
CIntVNum now contains number of free interrupt.
-------------------------------------------------------------------------------
mov si,offset NoFndOneS ; didn't find one
call prtstring
jmp short DoneErr

------------------------------------------------------------------------------
Print message telling of the glad tidings that you have found a free entry
------------------------------------------------------------------------------

FndOne:
mov si,offset FndOneS
call prtstring

------------------------------------------------------------------------------
at the moment bx points to next entry after the free one. load ax with that offset, and then move it back 4 bytes so it points to free entry
Then print the offset of free entry
------------------------------------------------------------------------------
mov ax,bx
sub ax,04 ; backup to first of vector
call prthex

------------------------------------------------------------------------------
Point si at first part of message and then print it
------------------------------------------------------------------------------
mov si,offset IntNumS
call prtstring

-------------------------------------------------------------------------
Load al with free int number & print second part of message
------------------------------------------------------------------------
mov al,CIntVNum ; display current int number
call prthexs ;
mov dl,'h' ; print 'h'
mov ah,02 ;
int 21h ;
push cs
pop ds

------------------------------------------------------------------------
Load interrupt table with address of your isr
------------------------------------------------------------------------
mov al,CIntVNum ; vector to change
mov ah,25h
mov dx,offset cs:OurStart
int 21h

------------------------------------------------------------------------
Don't need memory allocated for environment strings when 
prog was loaded - so free it
-----------------------------------------------------------------------
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 ;

-------------------------------------------------------------------------
Calculate amount of memory needed for resident part of program
including the program segment prefix
Then terminate and stay resident
-------------------------------------------------------------------------
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

---------------------------------------------------------------------------
Error occurred, so terminate without staying resident
---------------------------------------------------------------------------

DoneErr:
mov ah,4Ch ; exit to DOS (no TSR)
int 21h ; 


prtstring proc near

uses ax dx si

-------------------------------------------------------------------------
load next character then increment si so that it points to
following character
-------------------------------------------------------------------------

ps1:
mov dl,[si] ; Get character
inc si ; Point to next one

------------------------------------------------------------------------
strings used by this routine are null terminated, so test for null byte.
or dl,dl is equivalent to cmp dl, 0
if it is end of string jump out of loop
------------------------------------------------------------------------

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

--------------------------------------------------------------------------
point ds:bx at array of hex digits
--------------------------------------------------------------------------
mov bx,offset Hex
push ax

---------------------------------------------------------------------------
procedure called with 8 bit hex number (say 4Dh). shr to get upper four bits into lowere for bits (ie 4 in this example).
al now contains index into string of hex digits
---------------------------------------------------------------------------
shr al,04h

---------------------------------------------------------------------------
load digit from string into al, and print it
--------------------------------------------------------------------------

xlatb
mov dl,al
mov ah,02
int 21h
pop ax

--------------------------------------------------------------------------
now isolate lower four bits, and then repeat all of the above
--------------------------------------------------------------------------

and al,0Fh
xlatb
mov dl,al
mov ah,02
int 21h
ret
PrtHexs endp

-------------------------------------------------------------------------------
I'll leave you to figure this one out for yourself
-------------------------------------------------------------------------------
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


----------------------------------------------------------------------------
int the strings below:
10 = ascii code for carriage return
13 = ascii code for line feed
-----------------------------------------------------------------------------

CIntVNum db 34h ; starting with int 34h
StartIt db 13,10,'Interrupt Install Util Version 01.00b'
db 13,10,'Forever Young Software(r) (C)opyright 1984-2000',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

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.00b
Author: Ben Lunt (Forever Young Software(R))
Date: 8 Dec 1998
Assembler: NBASM 00.23.xx
; This is a small util. to show how to create your own
; interrupt.
;
; (version 1.00b - original release)
;
; OUTINT.ASM
; Forever Young Software
; Copyright 1997
; All rights reserved
; Version 1.00b
.model tiny
.186
org 100h
start: jmp short InstallIt
;*******************************************************************
;;;; our interrupt code and data goes here
.algnw ; 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.00b'
db 13,10,'Forever Young Software(r) (C)opyright 1984-2000',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

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.