Reputation: 21
I'm trying to override the default interruption when a key is pressed. Here is my code : do not call the kbd_handler and change 'port60' How can I resolve this? What do you think is causing it?
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
Upvotes: 2
Views: 1630
Reputation: 9899
Several errors found in your code:
To retrieve and restore the interrupt vector you need to set the segment register of your choice to zero. Michael Petch made the same remark. So let's use the ES
segment register.
...
xor dx, dx
mov es, dx
mov dx, word ptr es:[bx]
...
When you saved the interrupt vector on the stack, you have to restore it in reverse order! You've done it the other way round.
In the new handler you can only use the CS
segment register as an override straight on.
in al, 60h
mov byte ptr cs:[port60], al
It's not useful to push/pop registers that you don't intend to change. Furthermore push sp
and pop sp
are always reduntant.
Since your main program loop uses an unconditional jump the code to restore things back to normal will never run.
TEST_2 :
call printc
call delay_cx
jmp test_2
mov ax, MAIN <-- You're code will never get here!
mov dx, ax
When you use call delay_cx
you still need to set the CX
register to a suitable value.
I see that your program is still very much a work in progress. Lots of temporary code that isn't used anymore. Remove what isn't needed in order to not loose on readability.
Looking at the messages that you've written, I dare suggest that you delimit these in some way.
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
Upvotes: 2