更换INT 9 ISR时发生崩溃,但在链接时不会发生崩溃

时间:2018-03-28 02:15:04

标签: assembly x86-16

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

我想完全取代原来的9 ISR。我没有使用int 16h BIOS键盘服务,如果键盘数据区域没有管理,我也不介意。事实上,取代ISR会对我有两个好处。

  1. 我自己的ISR可能会更快。我可以快速对传入的make / break代码作出反应,以一种特定于我需要的方式决定应该做什么,然后立即恢复我的程序。

  2. 我不再需要在主循环中包含代码来清除提前输入缓冲区。

  3. 这是我写的一个安装了键盘(int 9)和定时器(int 1ch)ISR的程序。程序通过向屏幕写入像素来响应击键。在这个例子中,键盘ISR被链接到原始的int 9 ISR,它在DOSBox和硬件(奔腾笔记本电脑运行DOS)中都能很好地工作。定时器ISR每隔55毫秒更新缓冲区中的像素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过程,以便它向PIC发送EOI并执行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是否安全?我知道它在机器之间的具体情况以及它在幕后的作用,但是它经常做一些对系统至关重要的事情吗?据我所知它只是管理键盘数据区,对吧?

1 个答案:

答案 0 :(得分:1)

正如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