截取15H/4FH以使用热键

问题描述 投票:0回答:1

我有一个标志变量,按 ctr+alt+s 时应为 1,按 ctrl+alt+h 时应为 0。 Int 09 是由按键调用的硬件中断,正如我在课堂上被告知的那样,它将进一步调用软件中断 15H/4FH。我需要检查是否为中断 15 调用了服务 4F,如果是,我需要拦截该中断以创建“键盘钩子” - 我丢失了键盘钩子讲座中的笔记,并且不太记得了。我只记得,如果调用 INT 15H 时使用的服务号是 4FH,那么我需要拦截并调用键盘钩子,否则照常进行。

我知道我可以使用 40H:17H 处的键盘字节来检查 alt 和 ctrl。我记得按下按键时会自动调用 int 09,我需要检查端口 60H 处的键盘以检查 s 或 h 的扫描码。

这是我检查服务 4F 的代码:

 ; Input Handling
    
    
     ; get-vector safe keep orignal int 15
    
    mov ax, es:[15 * 4] 
    
    mov word ptr oldInt15, ax 
    
    mov ax, es:[15 * 4 + 2]
    mov word ptr oldInt15[2], ax
      
    ; Decide wether to call keyboard hook  
      
    cmp ah, 4Fh
    je _KeyboardHook

我只知道服务号码会在里面啊,所以这就是我正在检查的。它真的会在按键时自行发生吗?

这是我对键盘挂钩的尝试:

_KeyboardHook:
     
   
    
    in al, 60h
    cmp al, 16h
    je _set
    cmp al, 0bh
    je _clear
    
    
    _set:
    mov ax, 40h
    mov es, ax
    
    mov ax, es:[0017]
    
    and ax, 00110000B
    jz _dontSet
    
    mov boolDisplay, 01h
    
    _dontSet:
    jmp _Further
    
    _clear:
    
    mov ax, 40h
    mov es, ax
    
    mov ax, es:[0017]
    
    and ax, 00110000B
    jz _dontClear
    
    mov boolDisplay, 00h
    
    _dontClear:
    jmp _Further 

此时我不确定是否要拦截 15H,因为如果使用服务 4F 调用它,然后它发生了变化,我们是否需要等待 INT 15H 再次被调用,以便调用更改后的向量?我开始认为我只应该拦截并更改该向量的服务 4F。我已经完成了矢量拦截,但我不确定如何拦截服务。无论如何,这有意义吗?你能使用这样的热键吗?

_Further: 之后的代码由 boolDisplay 标志控制,但当我按下预期的热键时没有任何反应

assembly x86 keyboard masm dosbox
1个回答
0
投票

你的代码有点乱!

不仅很难(甚至不可能)跟踪代码的执行,而且还包含几个所写的错误:

mov ax, es:[15 * 4 + 2]
mov word ptr oldInt15[2], ax

; Decide wether to call keyboard hook  
cmp ah, 4Fh

中断是15h,这是一个十六进制数。你错误地写了一个十进制数15。一旦你使用了AX寄存器,就不要指望在AH中找到函数号。请记住 AL 和 AH 是 AX 的一部分。

in al, 60h
cmp al, 16h
je _set
cmp al, 0bh
je _clear

您从哪里获得这些扫描码? 1Fh 代表“s”,23h 代表“h”。

and ax, 00110000B
jz _dontSet

and ax, 00110000B
jz _dontClear

您从哪里获得这些位设置?位 2 用于 CTRL,位 3 用于 ALT。编号从右侧开始,因此正确的掩码是

00001100b
。此外,测试零还不足以确保同时按下 CTRL ALT 。

首先hook中断15h。

注意它是十六进制的15h(所以不是你写的十进制15)。
您在程序启动时挂钩向量并在程序终止之前释放挂钩:

; Create .COM program. We'll have CS=DS=ES=SS.
    org     256
; Hook the 15h interrupt.
    xor     ax, ax
    mov     es, ax
    cli
    mov     ax, offset MyInt15
    xchg    ax, [es:0015h*4]
    mov     [Int15+1], ax                ; Patch the 'jmpf' instruction (offset)
    mov     ax, cs
    xchg    ax, [es:0015h*4+2]
    mov     [Int15+3], ax                ; Patch the 'jmpf' instruction (segment)
    sti

    ...

; Restore the 15h interrupt.
    cli
    mov     ax, [Int15+1]
    mov     [es:0015h*4], ax
    mov     ax, [Int15+3]
    mov     [es:0015h*4+2], ax
    sti
; Terminate.
    mov     ax, 4C00h   
    int     21h
; -----------------------------------
boolDisplay db 0
; -----------------------------------

然后编写替换处理程序。

注意 AH 寄存器中的函数编号 4Fh。您可以链接到原始的

int 15h
处理程序来处理其他任何事情:

MyInt15:
    cmp     ah, 4Fh                     ; Is it Keyboard Intercept ?
    jne     Int15

    ...

Int15:
    ; jmpf    0:0                         ; Chain to the original handler
    db  0xEA, 0, 0, 0, 0
; -----------------------------------

然后检查您的热键。

扫描码位于 AL 寄存器中,CTRLALT 的状态位于地址 0417h 的 BIOS 数据区域中(但不在您在问题中选择的位中!):

MyInt15:
    cmp     ah, 4Fh
    jne     Int15
    push    ax
    push    ds
    xor     ax, ax
    mov     ds, ax
    test    byte ptr [0417h], 00001100b ; Bit 2 is 'Either CTRL'
    pop     ds                          ; Bit 3 is 'Either ALT'
    pop     ax
    jz      Int15                       ; Neither bit set
    jpo     Int15                       ; Only one bit set

    cmp     al, 1Fh                     ; Scancode of 's'
    je      SetBool
    cmp     al, 23h                     ; Scancode of 'h'
    je      ClearBool

Int15:
    ; jmpf    0:0                         ; Chain to the original handler
    db  0xEA, 0, 0, 0, 0

SetBool:
    mov     [cs:boolDisplay], 1
    iret
ClearBool:
    mov     [cs:boolDisplay], 0
    iret
; -----------------------------------
© www.soinside.com 2019 - 2024. All rights reserved.