0

キーが押されたときのデフォルトの割り込みをオーバーライドしようとしています。これが私のコードです:なぜそれが機能しないのかわかりません.他のINT番号(たとえば43h)で機能します.

mov al,9h
mov ah,25h
mov bx,seg int9h
mov ds,bx
mov dx,offset int9h
int 21h

(int9hは私のコードのラベルです)キーが押されたときに割り込みをフックする方法を知っている人はいますか?ありがとう !

編集:

mov     ax,2509h
mov     dx,offset int9h
int     21h            

int9h PROC
    ;do some stuff
    IRET 
int9h ENDP
4

2 に答える 2

2

私はこれにもう一度答えようとします - やや長ったらしい方法で。

Windows が普及する前は、DOS がコンピュータを支配していました。その機能を拡張するために、人々は TSR (終了して常駐) プログラムを作成していました。これらのプログラムは、さまざまな割り込み機能 (時計やキーボードなど) をフックし、終了してからメモリに常駐します。その結果、特定の割り込みが発生すると、これらのユーティリティの常駐コードが割り込みを処理し、元の割り込みハンドラを呼び出す可能性がありました。

このようなプログラムは、トランジェント部分とレジデント部分の 2 つのセクションで構成される構造になります。一時的な部分は、プログラムがコマンド ラインから呼び出されたときに実行されるコードです。これにより、常駐部分が既にインストールされているかどうかがチェックされます。常駐部分がインストールされている場合プログラムは単純に終了しますが、これが最初の呼び出しである場合、プログラムは最初に現在の割り込みハンドラーのアドレスを保存し、次に独自のコードを新しい割り込みハンドラーとしてインストールしてから、特別なハンドラ コードをメモリに残す DOS 呼び出し。

あなたが示したコードは、新しい割り込みハンドラーが割り込みテーブルにインストールされる一時的なプログラムの一部です。このコードは 1 回だけ実行する必要があり、新しい割り込みハンドラー自体の一部ではありません。

Windows の使用が広まると、TSR プログラムは時代遅れになりました。ある意味では、Windows で実行されるすべてのプログラムは TSR プログラムであり、キーボード割り込みハンドラ コードは、'OnKeyPress' 関数で (たとえば Delphi で) 処理されるキーボード イベントになります。

次のコードは、割り込みテーブルを変更します

mov ax, 2509h
mov dx, offset kb_handler
int 21h

アドレス *kb_handler* で始まるコードは、実際の割り込みハンドラです。

あなたがしているのは、割り込みを処理するのではなく、割り込みハンドラのアドレスを繰り返し設定することです。上記のコードは、プログラム自体のインストール時に 1 回だけ実行する必要があります。割り込みハンドラ コードは何度も呼び出されます。

これが物事をより明確にすることを願っています。

あなたが書いていないのは、あなたがこれをしている理由です

于 2012-10-15T05:33:48.373 に答える
1

アーカイブから次のコードを掘り出しました(1995年6月24日付け)。これは、両方のShiftキーが押された場合に画面を空白にする、私が作成したプログラムのキーボードハンドラーです。

kb_int      proc    far
            pushf                           ;Save FLAGS
            push    ax                      ;Save AX
            in      al,60h                  ;Read the scan code
            mov     cs:[scancode],al        ;Save it
            pop     ax                      ;Restore AX
            popf                            ;Restore FLAGS
            pushf                           ;Push FLAGS
            call    cs:[int09h]             ;Call previous handler
            sti                             ;Enable interrupts

            test    cs:[scancode],80h       ;Exit if high bit of scan
            jnz     kb_exit                 ;  code is set

            push    ax                      ;Save AX and ES
            push    es
            mov     ax,40h                  ;Point ES to the BIOS
            mov     es,ax                   ;  Data Area
            mov     al,es:[17h]             ;Get keyboard flags
            and     al,03h                  ;Zero the upper 6 bits
            cmp     al,03h                  ;Are the Shift keys pressed?
            pop     es                      ;Restore AX and ES
            pop     ax
            jne     kb2                     ;Branch if they're not
            call    disable_video           ;Blank the screen
            iret                            ;Return from interrupt
kb2:        push    cs:[time]               ;Reset countdown timer
            pop     cs:[count]
            cmp     cs:[blanked],0          ;Is the screen blanked?
            je      kb_exit                 ;If not, then exit
            call    enable_video            ;Unblank the screen
kb_exit:    iret                            ;Return from interrupt
kb_int      endp

そして、これが割り込みをフックするコードです-これはプログラムの最初に実行されます

            mov     ax,3509h                ;Hook interrupt 09H
            int     21h
            mov     word ptr int09h,bx
            mov     word ptr int09h[2],es
            mov     ax,2509h
            mov     dx,offset kb_int
            int     21h

プログラム全体が長すぎてここに投稿できません-33KB。しかし、あなたは何をすべきかの例を見たいだけです...。

さまざまなalt/ctrl/key関数をチェックする別の例を次に示します。

even
New_09     proc   far
           sti
           pushf
           push   ax
           mov    ah, 2                 ; get shift key status
           int    16h
           and    al, 0Fh
           cmp    al, 12                ; alt/ctrl?
           jne    @@0                   ; no
           in     al, 60h
           cmp    al, 19                ; 'R'?
           je     @@1                   ; yes
           cmp    al, 31                ; 'S'
           je     @@1                   ; yes
           cmp    al, 16                ; 'Q'
           je     @@1                   ; yes
@@0:       pop    ax                    ; exit if not my hotkey
           popf
           jmp    cs:old_09

@@1:       push   bp
           mov    bp, ax                ; save scan code
           in     al, 61h               ; reset keyboard
           mov    ah, al
           or     al, 80h
           out    61h, al
           mov    al, ah
           out    61h, al
           cli
           mov    al, 20h
           out    20h, al
           sti

           mov    ax, bp                ; restore scan code
           cmp    al, 16                ; was it Q?
           jne    @@GetMode

なぜすべてのインとアウトが必要だったのか今は覚えていません(このコードは1992年5月14日から-20年前です!!!!)。

于 2012-10-14T15:07:54.923 に答える