Upload
tyrone-townsend
View
217
Download
0
Tags:
Embed Size (px)
Citation preview
ECE291 Lecture 10 2
Interrupt service routines
• DOS facilities to install ISRs
• Restrictions on ISRs– Currently running program should have no idea that it was
interrupted. – ISRs should be as short as possible because lower priority
interrupts are blocked from executing until the higher priority ISR completes
Function Action
INT 21h Function 25h Set Interrupt vectorINT 21h Function 35h Get Interrupt vectorINT 21h Function 31h Terminate and stay resident
ECE291 Lecture 10 3
Installing ISRs
Let N be the interrupt to service• Read current function pointer in vector table
– Use DOS function 35h
– Set AL = N
– Call DOS Function AH = 35h, INT 21h
– Returns: ES:BX = Address stored at vector N
• Set new function pointer in vector table– Use DOS function 25h
– Set DS:DX = New Routine
– Set AL = N
– DOS Function AH = 25h, INT 21h
ECE291 Lecture 10 4
Installing ISR
• Interrupts can be installed, chained, or called
• Install New interruptreplace old interrupt
• Chain into interruptService myCode first
• Call Original InterruptService MyCode last
MyIntVector Save Registers Service Hardware Reset PIC Restore Registers IRET
MyIntVector Save Registers MyCode Restore Registers JMP CS:Old_Vector
MyIntVector PUSHF CALL CS:Old_Vector Save Registers MyCode Restore Registers IRET
ECE291 Lecture 10 5
Timer interrupt example
• In this example we will patch the ISR for the Timer Interrupt
• Our ISR will count the number of timer interrupts received
• Our main program will use this count to display elapsed time in minutes and seconds
ECE291 Lecture 10 6
About the PC timer
• We’ll examine it in detail when we look at the 8253• You can view it as a clock that ticks and sends a
signal to your processor approximately every 1/18.2 seconds
• It is also called the “eighteenth of a second” • We’ll find out where this 18.2 comes from later• You can approximately count minutes and seconds
as follows– For every 18 ticks of the timer we add 1 second– For every 60 seconds we add one minute and reset the
counters for seconds
ECE291 Lecture 10 7
ISR overview
• Install the ISR for vector 08h• Call original timer interrupt• Increment a counter on every interrupt from the timer (count)• Increment a second counter (scount) when count=18 and reset
count• Increment a minute counter (mcount) when scount=60 and reset
the second counter• The program will print the scount, mcount and count values in
red, green and blue colors• It will look as a (somewhat low-resolution) timer printed in your
screen
ECE291 Lecture 10 8
Timer interrupt - main proc skeleton;====== Variables ===================; Old Vector (far pointer to old interrupt function)oldv RESW 2count DW 0 ;Interrupt counter (1/18 sec)scount DW 0 ;Second counter mcount DW 0 ;Minute counterpbuf DB 8 ;Minute counter;====== Main procedure =====..start…;----Install Interrupt Routine-----call Install ;Main program (print count values) .showcMov ax, [mcount] ;Minute Count…
call pxymov ax, [scount] ;Second Count…call pxymov ax,[count] ;Interrupt Count (1/18 sec)… call pxymov ah,1int 16h ;Check for key press jz .showc ;Quit on any key
;---- Uninstall Interrupt Routine-----call UnInst ;Restore original INT8…call mpxit
ECE291 Lecture 10 9
Timer interrupt – complete main proc..start
mov ax, cs ;Initialize DS=CS
mov ds, ax
mov ax, 0B800h ;ES=VideoTextSegment
mov es, ax
call install ;Insert my ISR
showc:
mov ax, [mcount] ;Minute Count
mov bx, pbuf
call binasc
mov bx, pbuf
mov di,0 ;Column 0
mov ah,00001100b ;Intense Red
call pxy
mov ax,[scount] ;Second Count
mov bx,pbuf
call binasc
mov bx, pbuf
mov di,12 ;Column 6 (DI=12/2)
mov ah,00001010b ;Intense Green
call pxy
mov ax,[count] ;Int Count (1/18th sec)
mov bx,pbuf
call binasc
mov bx, pbuf
mov ah,00000011b ;Cyan
mov di,24 ;Column 12 (DI=24/2)
call pxy
mov ah,1
int 16h ;Key Pressed ?
jz showc
Call UnInst ;Restore original INT8
mov ax,4c00h ;Normal DOS Exit
int 21h
ECE291 Lecture 10 10
Timer interrupt – PXY and Install interrupt
;pxy (bx = *str, ah = color, di = column)pxy
mov al, [bx]cmp al, ‘$'je .pxydonemov es:[di+2000], axinc bxadd di,2jmp pxy
.pxydoneret
;====== Install Interrupt =====
install ;Install new INT 8 vector
push es
push dx
push ax
push bx
mov al, 8 ;INT = 8
mov ah, 35h ;Read Vector Subfunction
int 21h ;DOS Service
mov word [oldv+0], bxmov word [oldv+2], esmov al, 8 ;INT = 8mov ah, 25h ;Set Vector Subfunction
mov dx, myint
;DS:DX point to functionint 21h ;DOS Service
pop bx pop axpop dxpop esret
ECE291 Lecture 10 11
Timer interrupt – uninstall interrupt
;====== Uninstall Interrupt ===========
UnInst ; Uninstall Routine (Reinstall old vector)
push ds
push dx
push ax
mov dx, word [oldv+0]
mov ds, word [oldv+2]
mov al, 8 ; INT = 8
mov ah, 25h ; Subfunction = Set Vector
int 21h ; DOS Service
pop ax
pop dx
pop ds
ret
ECE291 Lecture 10 12
Timer interrupt – ISR code
;====== ISR Code =========myint
push ds ;Save all registerspush axmov ax, cs ;Load default segmentmov ds, axpushf ;Call Orig Function w/flagscall far [oldv] ;Far Call to existing routine
inc word [count];Increment Interrupt
countcmp word [count],18jne .myintdone
inc word [scount] ;Next second mov word [count], 0cmp word [scount], 60jne .myintdoneinc word [mcount] ; Next minutemov word [scount], 0
.myintdonepop ax ;Restore all Registerspop dsiret ;Return from Interrupt
ECE291 Lecture 10 13
The complete code with exe
• www.ece.uiuc.edu/ece291/lecture/timer.asm• www.ece.uiuc.edu/ece291/lecture/timer.exe
ECE291 Lecture 10 14
Replacing An Interrupt Handler;install new interrupt vector
%macro setInt 3 ;Num, OffsetInt, SegmentInt
push ax
push dx
push ds
mov dx, %2
mov ax, %3
mov ds, ax
mov al, %1
mov ah, 25h ;set interrupt vector
int 21h
pop ds
pop dx
pop ax
%endmacro
;store old interrupt vector
%macro getInt 3 ;Num, OffsetInt, SegmentInt
push bx
push es
mov al, %1
mov ah, 35h ;get interrupt vector
int 21h
mov %2, bx
mov %3, es
pop es
pop bx
%endmacro
ECE291 Lecture 10 15
Replacing An Interrupt HandlerCR EQU 0dhLF EQU 0ah
SEGMENT stkseg STACK resb 8*64stacktop:
SEGMENT code
Warning DB “Overflow - Result Set to ZERO!!!!”,CR,LF,0
msgOK DB “Normal termination”, CR, LF, 0
old04hOffset RESWold04hSegment RESW
New04h ;our new ISR for int 04
;occurs on overflow
sti ;re-enable interrupts
mov ax, Warning
push ax
call putStr ;display message
xor ax, ax ;set result to zero
cwd ;AX to DX:AX
iret
ECE291 Lecture 10 16
Replacing An Interrupt Handler
mov ax, msgOK
push ax
call putStr
Error:
;restore original int handler
setInt 04h, [old04hOffset], [old04hSegment]
mov ax, 4c00h
int 21h
..startmov ax, csmov ds, ax
;store old vectorgetInt 04h, [old04hOffset], [old04hSegment]
;replace with address of new int handlersetInt 04h, New04h, cs
mov al, 100add al, alinto ;calls int 04 if an overflow occurredtest ax, 0FFhjz Error
NOTES• INTO is a conditional instruction that acts only when the overflow flag is set• With INTO after a numerical calculation the control can be automatically routed to a handler routine if the
calculation results in a numerical overflow.• By default Interrupt 04h consists of an IRET, so it returns without doing anything.
ECE291 Lecture 10 17
Reentrancy
• What happens if– An ISR for some devices is executing and it has enabled
interrupts– Another interrupt from the same device comes along…The
program may not behave correctly• Assume that the ISRs modify some register and store its value
in a memory location
• The previous ISR might have already modified the register but didn’t have the time to store the value in the memory locations
• The new ISR will save this register but it will try to update the memory location, which is in an inconsistent state
ECE291 Lecture 10 18
Reentrancy
AnISR; assume scount=3, MSEC=950push dspush axmov ax, csmov ds, axmov ax, [MSEC] add ax, 55 ; ax=1005cmp ax, 1000jb SetMsec; Assume that another interrupt occurs at this pointinc [scount] ; the second interrupt will set scount=4 sub ax, 1000 ; mov [MSEC], ax; the second interrupt will set MSEC=5…; but the interrupted ISR will reexecute the inc so scount will be; set to 5 although the timer has not ticked 55 times!!!!pop axpop ds
ECE291 Lecture 10 19
Reentrancy
• The code between the mov ax, [MSEC] and the mov [MSEC], ax must be executed atomically, without any interruptions
• This is called a critical region• You can protect a critical region from being
interrupted by using:pushf ;preserve the current I flag state
cli ; turn off interrupts
… ; critical region
popf ; restore the I flag state
ECE291 Lecture 10 20
Reentrancy in practice
• First thing to remember: don’t call DOS from your ISRs, DOS is not reentrant– DOS subroutines assume to be entered by a single point at any
time– If you write an ISR and attempt to call DOS you will most likely
hang the machine forever
• Second thing to remember: BIOS is not reentrant• There are ways to check if you’re executing inside DOS by
testing a flag (function code 34h)– If the flag is 0 it is safe to call DOS– If the flag is 1 it might not be safe to call DOS– You can also check if DOS is “idling” (function code 28h), in that
case it is safe to call DOS
ECE291 Lecture 10 21
DOS Memory Usage
00000h
Interrupt vector003FFh
Various DOS/BIOS vars
Free memory area for use
by programs
0BFFFh
High memory area
Video, ROM, adapter memory
0FFFFh
Free memory pointer
ECE291 Lecture 10 22
DOS Memory Usage
00000h
Interrupt vector003FFh
Various DOS/BIOS vars
Memory in use by your program
0BFFFh
High memory area
Video, ROM, adapter memory
0FFFFh
Free memory pointerFree memory area
ECE291 Lecture 10 23
Terminate and Stay Resident (TSR)
00000h
Interrupt vector003FFh
Various DOS/BIOS vars
Marked by the program as
resident and protected by DOS
0BFFFh
High memory area
Video, ROM, adapter memory
0FFFFh
Free memory pointer
Free memory area
ECE291 Lecture 10 24
Terminate and Stay Resident (TSR)
• Your program can have a resident portion and a transient portion
• The main program, normal data, support routines etc, are usually transient
• You can define ISRs and maintain them in memory after the program terminates using the resident portion
• Use DOS function 31h with the size of the resident portion passed in dx
ECE291 Lecture 10 25
Terminate and Stay Resident (TSR)
• If you want to use resident ISR’s you should define them in the lower parts of your memory address space
• You have to set your DS properly– The resident code has no idea about the values of the segment
registers
– You have to set the data segment to the value of your code segmentpush ds
push cs
pop ds ; this moves cs to ds
…
pop ds