Set and reset keyboard Interrupt Service Routines in x86 real mode within DOS with Assembly

Viewed 1263

How do you properly set, and then reset, the keyboard ISR in DOS? (x86 assembly, real mode, 16 bit, with TASM)

I have the following assembly code which sets up my ISR for the keyboard. All it is supposed to do is print out a sentence each time a key is pressed, up to five times. Then it is supposed to exit.

It seems like the ISR is being installed correctly. It will print out a sentence each time a key is pressed (once for down, once for up). However, it appears as though I am uninstalling the ISR incorrectly as I'm unable to enter text into the DOS command line after running the program.

(I have updated the code below to store/restore DS in the ISR, read from port 60h, and handle EOI calls thanks to feedback received so far.)

.model              small
.data

our_text            db      "Interrupt intercepted", 0dh, 0ah, "$"
old_int_seg         dw      0
old_int_off         dw      0
keyCount            dw      0
.code
.startup
                    cli
                    mov     ah, 035             ; get current keyboard int vector
                    mov     al, 09h             ; and save it, so we can restore it later
                    int     21h                 
                    mov     [old_int_off], bx   
                    mov     bx, es
                    mov     [old_int_seg], bx

                    mov     ax, cs
                    mov     ds, ax              ; load data segment with code segment 
                                                ;(the one we are in now)
                    mov     ah, 25h             ; Set Interrupt Vector Command
                    mov     al, 9               ; Interrupt to replace
                    lea     dx, ISR             ;load dx with our interrupt address
                    int     21h
                    sti

                    mov     ax,@data
                    mov     ds,ax
infinite:
                    mov     ax,keyCount[0]
                    cmp     ax,5
                    jl      infinite                ;check for 5 presses


                    cli                             ;restore old interrupt
                    mov     ax, [old_int_seg]
                    mov     ds, ax
                    mov     dx, [old_int_off]
                    mov     ah, 25h
                    mov     al, 09h
                    int     21h
                    sti

                    mov     ah,4Ch                  ; quit
                    mov     al,00h
                    int     21h

ISR                 proc    far
                                                    ; save old registers
                    push    ax
                    push    cx
                    push    dx
                    push    bx
                    push    sp
                    push    bp
                    push    si
                    push    di
                    push    ds

                    mov     ax,@data                ;print text
                    mov     ds,ax
                    xor     ah,ah
                    mov     ah, 9
                    lea     dx, our_text
                    int     21h

                    mov     ax,keyCount
                    inc     ax
                    mov     [keyCount],ax

                    in      al, 60h

                    ; send EOI to keyboard
                    in      al, 61h
                    mov     ah, al
                    or      al, 80h
                    out     61h, al
                    mov     al, ah
                    out     61h, al

                    ; send EOI to master PIC
                    mov     al, 20h
                    out     20h, al

                    pop     ds
                    pop     di
                    pop     si
                    pop     bp
                    pop     sp
                    pop     bx
                    pop     dx
                    pop     cx
                    pop     ax
                    iret
ISR                 endp     

What's wrong with how I'm restoring the original keyboard ISR? Why am I unable to type anything into the command prompt in DOS after running the program?

1 Answers
Related