The 8086 systems have 256 interrupts. Every interrupt is associated with a code
routine called RTI, which is executed when that interrupt is called. Not all 256
interrupts are defined (there are no routines associated with all the 256 iunterrupts).
Most of the BIOS interrupts are initialized when the system starts. When the operating system loads, this defines/redefines, at its turn, some of the interrupts to provide the system services that are specific to it (e.g. DOS rewrites the routine associated to the 21h interrupt to implement the services specific to DOS operating system).
The routines of some soft interrupts (BIOS and DOS) can manage differentially the generated interrupt, depending on a value that is specified into a registry. We say that the respective interrupt provides more 'services' or 'functions'.
Having a limited number of interrupts and a large number of routines that must be implemented, the systems and the applications usually use the next convention:
-
into the AH registry will be stored the number of the function that will be
used.
- Into
the rest of the registries will be put the rest of the parameters needed for executing
that function (see documentation=>NG)
- The RTI will check at every call the number of the function that must be called and will leave the control to the coresponding routine.
To memorate the points of entries of the 256 interrupts, are used memory addresses from 0000h:0000h =>0000h : 0400h(exclusively). The address of an interrupt handler is formed by:
- Segment address on 16 bits
-
Offset on 16 bits.
So, an address of an interrupt handler needs 2*16 bits = 32 bits ( 2 words = 4 Octets ) to be memorated. To memorate 256 addresses 1024 octets are needed -> exactly the memory space between 0000:0000 and 0000:0400h.
To redirect an interrupt handler it is sufficient to memorate into the memory location, where its entry point is stored, the address of the new entry point for that interrupt handler
Ex1:
To redirect the interrupt 10h ( video functions) with a handler written by us the following addresses will be stored
0000:[4*10h+2] => The segment address of The New Handler
0000:[4*10h]
=> The Offset handler.
Right after meorating the address of the new handler, the control will be transfered to it every time when a call to the 10h interrupt will be generated.
Genarally, rediracting an interrupt means:
- Saving into a memory zone the address of the old handler.
- Setting the address of the new handler for the interrupt.
The DOS system has two functions that
allow obtaining the address of an interrupt handler (see int 21h function 35h), respectively setting a new interrupt handler(int 21h, function 25h).
Ex2: To recover the address of the handler for the 10h
interrupt and redirecting it to a user handler:
….
Addr_int10
dd ?
…
mov ah,
3510h
int 21h ;returns in ES:BX the address of the original
handler
;saves the address of the original
handler
mov word ptr [addr_int10+2],
ES
mov word ptr
[addr_int10], BX
;installs the new interrupt handler
mov ax,
2510h
;it is assumed that the new handler is in the current code segment
mov ax,
cs
mov ds,
ax
mov dx, offset
<handler>
int
21h
;the new interrupt handler is set
To write a DOS interrupt handler that works properly it is necessary to know the following:
·
The call of an interrupt
handler may appear in any moment in the execution of a program (especially when
we talk about system interrupts as the time interrupt 08h or the keyboard interrupt
09h). So it is necessary to have an execution time as short as possible to not "embarrass"
the execution of the interrupted program. Also, a handler must not corrupt
the data zones or the stack of the interrupted programs.
·
The content of the
registries must be kept (saved) to permit, when the handler is finished, the normal
continuation of the executing of the interrupted program.
· At the entry into the routine of the handler, the stack used is the stack of the interrupted program. So the handler will use the stack of the interrupted handler. If the code of the handler alocates too much memory space into the stack it is possible to need more memory than the max dimension of it and to corrup the content of the stack. Another stack will be used in this case.
· It is necessary to consider the case when the interrupt handler is called once more while it is handling a previous event (it must be written in such manner that it could be re-entrant) => the handler interrupts itself. The whole context must be saved to permit the continuation of the execution (the local variables specific to the handler).
· The interrupt 21h (DOS functions) is not reentrant => if a program is interrupted in the middle of a DOS function call and our handler calls at its turn DOS functions, this will probably lead to system blocking. The interrupt 21h is not reentrant because it uses a static stack. So, the interrupt of a running DOS function and the call of another DOS function will lead to the destroy of the content of the stack for the interrupted function.
· In the case when the redirect of one function is realised only to add functionality or to modify one of the functions of the interrupt, the original handler will also be called to handle the cases that our handler does not take into consideration.
· When a program ends (except the case when it remains rezident) it is absolutely necessary the restore of the modified interrupt vectors. Otherwise the operating system will continue to call the handler of which memory zone is no longer allocated and will, most probably, be modified when the next program will be launched into execution. The consequence will be that the control of executioon will be transfered to an invalid memory location.
Observations: