我正在尝试覆盖按下按键时的默认中断。 这是我的代码:不要调用 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
最佳答案
在您的代码中发现几个错误:
要检索和恢复中断向量,您需要将您选择的段寄存器设置为零。迈克尔·佩奇也发表了同样的言论。因此,让我们使用
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
当您使用
calldelay_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
关于assembly - 8086 assembly INT 9h : keyboard ISR implementation,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39782865/