Assembly 8086汇编INT 9h:键盘ISR实现
我试图在按键时覆盖默认的中断。 下面是我的代码:不要调用kbd_处理程序并更改“port60” 我如何解决这个问题?你认为是什么引起的Assembly 8086汇编INT 9h:键盘ISR实现,assembly,x86-16,Assembly,X86 16,我试图在按键时覆盖默认的中断。 下面是我的代码:不要调用kbd_处理程序并更改“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 ;f
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
浏览这个-第一件让我感到奇怪的事情是
用于检索和更新中断向量mov-dx,word-ptr[bx]
表示DS,因此与mov-dx,单词ptr[bx]
相同。您已将DS设置为MAIN的段。问题是中断向量表从地址0x0000:0x0000开始。在中断表中更新/读取值时,应考虑将ES设置为0,然后使用段覆盖。如果您将ES设置为零,那么您应该能够执行类似于mov-dx,单词ptr-DS[bx]
这在新处理程序中是正确的,您只能直接使用CS段寄存器作为覆盖。问题是,在他的代码中,他有单独的代码段和数据段。如果该代码中的CS=DS,则覆盖就可以了,但是如果CS!=DS然后简单地使用CS重写可能不起作用。我不知道他在建立什么记忆模型,很难说。mov-dx,word ptr-ES:[bx]
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