我正在尝试在按下某个键时覆盖默认中断。 这是我的代码:不要调用kbd_handler并更改'port60' 我该如何解决这个问题?您认为是什么导致了它?
MAIN SEGMENT PUBLIC
ASSUME CS:MAIN, DS:DATA
MOV AX, MAIN ; Set up the Data Segment address
MOV DS, AX
mov bx, 9 * 4 ;find the int 9
mov dx, word ptr [bx]
push dx
mov dx, word ptr [bx] + 2
push dx
mov ax, DATA
mov DS, ax
mov es, ax
;mov bx, 09h * 04h
mov bx, 9 * 4 ;find the int 9
cli ; disable an interrupt
mov word ptr [bx], offset kbd_handler ; load your keyboard ISR
mov word ptr [bx] + 2, seg kbd_handler ;
sti ;enable interrupts
TEST_2 :
call printc
call delay_cx
jmp test_2
mov ax, MAIN
mov dx, ax
mov bx, 09h * 04h ;find the int 9
cli ; disable interrupt
pop dx
mov word ptr [bx], dx ;back to normal address
pop dx
mov word ptr [bx]+2, dx
sti ; enalbe interrupts
MOV AH, 4CH ;
INT 21H
PUBLIC kbd_handler
kbd_handler PROC NEAR
push ax
push bx
push cx
push dx
push sp
push bp
push si
push di
in al, 64h
test al, 01h
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
in al, 60h
mov byte ptr ds:[port60], al
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov al, 20h
out 20h, al
pop di
pop si
pop bp
pop sp
pop dx
pop cx
pop bx
pop ax
IRET
kbd_handler ENDP
PRINT PROC NEAR
CLD ;
PRINT_1 :
MOVSB
MOV AL, DL
STOSB
LOOP PRINT_1
RET
PRINT ENDP
delay_cx proc near ;
delay_1:
push cx ;
mov cx, 50 ;
delay_2:
loop delay_2 ;
pop cx ;
loop delay_1 ;
ret ;
delay_cx endp
PRINTC PROC NEAR
MOV AL, port60
MOV DL, AL
MOV AH, 02H
INT 21H
RET
PRINTC ENDP
MAIN ENDS
DATA SEGMENT
msg1 db 'Press and hold ESC'
msg2 db 'ESC pressed, release ESC'
msg3 db 'ESC released'
kbdbuf db 128 dup (0)
port60 db '1'
DATA ENDS
END
答案 0 :(得分:2)
您的代码中发现了几个错误:
要检索和恢复中断向量,您需要将所选的段寄存器设置为零。 Michael Petch也发了同样的话。因此,让我们使用ES
段注册。
...
xor dx, dx
mov es, dx
mov dx, word ptr es:[bx]
...
当您在堆栈中保存中断向量时,您必须以相反的顺序恢复它!你已反过来做过了。
在新的处理程序中,您只能直接使用CS
段寄存器作为覆盖。
in al, 60h
mov byte ptr cs:[port60], al
推送/弹出您不打算更改的寄存器没用。此外,push sp
和pop sp
始终是还原的。
由于您的主程序循环使用无条件跳转,因此将恢复正常的代码永远不会运行。
TEST_2 :
call printc
call delay_cx
jmp test_2
mov ax, MAIN <-- You're code will never get here!
mov dx, ax
当您使用call delay_cx
时,仍需要将CX
寄存器设置为合适的值。
我看到你的程序仍在进行中。很多临时代码不再使用了。删除不需要的东西,以免在可读性方面松动 看看你写的信息,我敢建议你以某种方式划分这些信息。
msg1 db 'Press and hold ESC',13,10,0
msg2 db 'ESC pressed, release ESC',13,10,0
msg3 db 'ESC released',13,10,0