替换INT 9 ISR时崩溃,但在链接时不会崩溃



这里有很多问题与覆盖默认的int 9 ISR有关,我已经仔细阅读了它们。我的问题似乎是独一无二的。编写键盘中断处理程序有许多好的例子,但它们涉及将原始ISR链接到

上。

我想完全替换原始的INT 9 ISR。我不使用INT 16H BIOS键盘服务,也不介意是否没有管理键盘数据区域。实际上,替换ISR将通过两种方式对我有益。

  1. 我自己的ISR可能会更快。我可以快速对传入的制作/中断代码做出反应,决定应以指定我的需求的方式做什么,然后立即恢复我的程序。

  2. 我不再需要在我的主循环中包含代码来清除类型的缓冲区。

这是我编写的程序,该程序安装了键盘(INT 9(和计时器(INT 1CH(ISRS。该程序通过将像素写入屏幕来响应击键。在此示例中,键盘ISR被链接到原始的INT 9 ISR上,并且在两个DOSBOX和硬件(Pentium笔记本电脑运行DOS(中效果很好。计时器ISR每55毫秒在缓冲区中更新Pixel 0。它用作程序的当前状态(是否崩溃(的指标。由于我用键盘ISR弄乱了,因此我不能总是知道该机器是否已锁定,例如,按下盖子锁定并查看LED指示灯是否亮起。

;----------------------------------------------------------------------------|                                                                     
 theStack SEGMENT STACK                                                     ;|
;____________________________________________________________________________|
 db 64 dup ('THESTACK')   
;----------------------------------------------------------------------------|
 theStack ENDS                                                              ;|
;____________________________________________________________________________|




;----------------------------------------------------------------------------|   
 varData SEGMENT                                                            ;|                            
;____________________________________________________________________________|

 pixCol db ?  ;current color index
 pixPos dw ?  ;current position in VGA pixel buffer
;----------------------------------------------------------------------------|
 varData ENDS                                                               ;|
;____________________________________________________________________________|



;----------------------------------------------------------------------------|
 code SEGMENT       
 assume cs:code,ds:varData
 oldInt9  dd 0                   ;original int 9 target
 oldInt1c dd 0                   ;original int 1c target                            
 main PROC                                                                  
 start:                                                                      
    mov ax, varData                            
    mov ds, ax                   ;Load the variable segment into ds           
;____________________________________________________________________________|



    call SET_VGA_256             ;set video mode 13h
    call INSTALL_ISR             ;install the ISRs
    mov ax, 40h
    mov es, ax                   ;access keyboard data area via segment 40h
loop0:
                                 ;clr type-ahead buff, prevents PC spkr beep
                                 ;(has to occur at some point if you don't 
                                 ;use int 16h BIOS keyboard services, and
                                 ;the original int 9 ISR is still handling
                                 ;keystrokes)
    mov WORD PTR es:[1ah], 1eh   ;set the kbd buff head to start of buff
    mov WORD PTR es:[1ch], 1eh   ;set the kbd buff tail to same as buff head

    inc pixCol                   ;increment the current pixel color
    inc pixPos                   ;increment the current pixel position
    cmp pixPos, 63999d           ;Is pixPos < pixel area
    jb loop0                     ;If so, loop back
    mov pixPos, 0                ;If not, reinit pixPos
    in al, 60h                   ;al <- last key press
    cmp al, 1                    ;Was the key Esc
    jne loop0                    ;If not, loop back
    call EXIT2DOS                ;Uninstall ISRs, restore text mode, exit.                 



SET_VGA_256 PROC
;SETS VIDEO MODE TO 13H (VGA 320x200 256 COLORS)
    push ax
    mov ax, 13h   ;320x200 256 colors
    int 10h       ;video mode set 
    pop ax 
    ret
SET_VGA_256 ENDP


INSTALL_ISR PROC
;PATCHES NEW VECTOR ENTRIES INTO THE INTERRUPT VECTOR TABLE.
;THE DEFAULT INPUT (INT 9H) ISR IS REPLACED WITH MY OWN INPUT HANDLING ISR.
;Int 1C TIMER ISR IS CHAINED FOR DEBUGGING PURPOSES.
;THE OLD VECTOR ENTRIES ARE BACKED UP. THEY WILL BE RESTORED BEFORE PROGRAM
;TERMINATION.

    push es

    ;// BACKUP THE OLD IVT ENTRIES //
    cli                                      ;disable hardware interrupts
    xor ax, ax
    mov es, ax                               ;es <- 0
    mov ax, WORD PTR es:[9*4]                ;ax <- offset part of IVT entry 
    mov WORD PTR cs:oldInt9, ax              ;store it in MSW of oldInt9
    mov ax, WORD PTR es:[9*4+2]              ;si <- segment part of IVT entry 
    mov WORD PTR cs:oldInt9+2, ax            ;store it in LSW of oldInt9
    mov ax, WORD PTR es:[1ch*4]     
    mov WORD PTR cs:oldInt1c, ax   
    mov ax, WORD PTR es:[1ch*4+2]  
    mov WORD PTR cs:oldInt1c+2, ax           ;store INT 1C IVT entry

    ;// INSTALL THE NEW INTERRUPT HANDLERS //
    mov WORD PTR es:[9*4], OFFSET INPUT_ISR   ;copy my new ISR offset to IVT   
    mov WORD PTR es:[9*4+2], cs               ;copy my code segment to IVT
    mov WORD PTR es:[1ch*4], OFFSET TIMER_ISR  
    mov WORD PTR es:[1ch*4+2], cs             ;do the same for int 1c entry    
    sti                                       ;enable hardware interrupts

    pop es
    ret
INSTALL_ISR ENDP


INPUT_ISR PROC
;PRINTS A PIXEL OF SOME COLOR INDEX TO SOME LOCATION IN THE PIXEL BUFFER
;WHEN A KEYSTROKE OCCURS. ONE KEYSTROKE GENERATES TWO INTERRUPTS, ONE FOR 
;KEY-DOWN, AND ONE FOR KEY-UP. 

    pushf                       
    cli                            ;disable hardware interrupts
                                   ;(disabled anyway upon entry)
    push ds
    push es
    push bx
    push ax
    mov bx, varData              
    mov ds, bx                     ;ds <- data segment
    mov bx, 0a000h
    mov es, bx                     ;es <- VGA pixel buffer
    mov bx, pixPos                 ;bx <- current pixel position
    mov ah, pixCol                 ;ah <- current pixel color 
    mov BYTE PTR es:[bx], ah       ;write the pixel to the buffer
    pop ax
    pop bx
    pop es
    pop ds
    popf
    jmp cs:oldInt9                 ;now execute original ISR

INPUT_ISR ENDP             


TIMER_ISR PROC
;USED FOR DEBUGGING. IF THE COLOR OF PIXEL POSITION 0 STOPS UPDATING, THINGS
;HAVE GONE VERY WRONG. 

    pushf                       
    cli                            ;disable hardware interrupts
                                   ;(disabled anyway upon entry)
    push ds
    push es
    push bx
    push ax

    mov bx, varData              
    mov ds, bx                     ;ds <- data segment
    mov bx, 0a000h
    mov es, bx                     ;es <- VGA pixel buffer
    mov ah, pixCol                 ;ah <- current pixel color
    xor bx, bx                     ;bx <- pixel position 0 
    mov BYTE PTR es:[bx], ah       ;write the pixel to the buffer

    pop ax
    pop bx
    pop es
    pop ds
    popf
    jmp cs:oldInt1c                ;now execute original ISR

TIMER_ISR ENDP



EXIT2DOS PROC
;UNINSTALL ISR, CLEAR THE TYPE-AHEAD BUFFER, RESTORE TEXT MODE, AND EXIT.
    cli                             ;disable hardware interrupts
    xor ax, ax
    mov es, ax
    mov ax, WORD PTR cs:oldInt9
    mov WORD PTR es:[9*4], ax 
    mov ax, WORD PTR cs:oldInt9+2
    mov WORD PTR es:[9*4+2], ax     ;Original int 9 ISR restored to IVT
    mov ax, WORD PTR cs:oldInt1c
    mov WORD PTR es:[1ch*4], ax 
    mov ax, WORD PTR cs:oldInt1c+2
    mov WORD PTR es:[1ch*4+2], ax   ;Original int 1c ISR restored to IVT
    sti                             ;enable hardware interrupts

                                    ;clear type-ahead buffer just before exit 
                                    ;to prevent dumping garbage characters
                                    ;to DOS prompt.
    mov ax, 40h
    mov es, ax                      ;access kbd data area via segment 40h
    mov WORD PTR es:[1ah], 1eh      ;set the kbd buff head to start of buff
    mov WORD PTR es:[1ch], 1eh      ;set kbd buff tail to same as buff head
                                    ;now the keyboard buffer is cleared.
    xor ah, ah                      ;select video mode function
    mov al, 3                       ;select 80x25 16 colors
    int 10h                         ;restore VIDEO back to text mode
    mov ax, 4c00h                   ;Terminate process DOS service
    int 21h                         ;Control returns to DOS
EXIT2DOS ENDP




;----------------------------------------------------------------------------|
 main ENDP                                                                  ;|
                                                                            ;|
 code ENDS                                                                  ;|
                                                                            ;|
 END start                                                                  ;| 
;____________________________________________________________________________|   

如果我稍微更改input_isr过程,以便它将EOI发送到PIC并执行IRET,原始INT 9 ISR将永远不会执行。

INPUT_ISR PROC
    pushf                       
    cli                            ;disable hardware interrupts
                                   ;(disabled anyway upon entry)
    push ds
    push es
    push bx
    push ax
    mov bx, varData              
    mov ds, bx                     ;ds <- data segment
    mov bx, 0a000h
    mov es, bx                     ;es <- VGA pixel buffer
    mov bx, pixPos                 ;bx <- current pixel position
    mov ah, pixCol                 ;ah <- current pixel color 
    mov BYTE PTR es:[bx], ah       ;write the pixel to the buffer
    mov al, 20h
    out 20h, al                    ;EOI 
    pop ax
    pop bx
    pop es
    pop ds
    popf
    iret
INPUT_ISR ENDP 

但是,这会在DOSBOX和硬件上引起问题。在DOSBOX中,它不会崩溃,但行为不稳定。像素通常会在窗户的右上角彼此串在一起,并且像素迟缓出现在屏幕上。计时器ISR仍执行,并且可以正常终止程序。在硬件中发生即时崩溃。计时器ISR停止更新其像素,并且必须重新启动机器。

替换INT 9 ISR甚至安全吗?我知道从机器到机器的特定方面的幕后影响是特定的,但是它经常做系统至关重要的事情吗?据我所知,它只是管理键盘数据区域,对吗?

正如迈克尔·皮奇(Michael Petch(在上述评论链中提到的,必须在结束ISR之前阅读端口60h,否则不会发生其他键盘中断。

更正的INPUT_ISR过程:

INPUT_ISR PROC
;PRINTS A PIXEL OF SOME COLOR INDEX TO SOME LOCATION IN THE PIXEL BUFFER
;WHEN A KEYSTROKE OCCURS. ONE KEYSTROKE GENERATES TWO INTERRUPTS, ONE FOR 
;KEY-DOWN, AND ONE FOR KEY-UP. 

    pushf                       
    cli                            ;disable hardware interrupts
                                   ;(disabled anyway upon entry)
    push ds
    push es
    push bx
    push ax

    mov bx, varData              
    mov ds, bx                     ;ds <- data segment
    mov bx, 0a000h
    mov es, bx                     ;es <- VGA pixel buffer
    mov bx, pixPos                 ;bx <- current pixel position
    mov ah, pixCol                 ;ah <- current pixel color 
    mov BYTE PTR es:[bx], ah       ;write the pixel to the buffer

    in al, 60h                     ;read port 60h, must always be done before
                                   ;terminating an int 9 ISR, or else no 
                                   ;keyboard interrupts will occur
    mov al, 20h
    out 20h, al                    ;EOI 
    pop ax
    pop bx
    pop es
    pop ds
    popf
    iret

INPUT_ISR ENDP      

最新更新