我有一个标志变量,按 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 标志控制,但当我按下预期的热键时没有任何反应
不仅很难(甚至不可能)跟踪代码的执行,而且还包含几个所写的错误:
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 。
注意它是十六进制的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 寄存器中,CTRL 和 ALT 的状态位于地址 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
; -----------------------------------