Real Mode, Interrupt vector replacement Crashing
-
20-08-2019 - |
Question
I'm trying to learn more about how systems really work underneath all the pretty graphics on top. So I'm currently playing with memory in the 512bytes that the BIOS loads on startup, can't really call it a bootloader at the moment I guess. Anyway, I'm replacing an interrupt vector but having issues with it. After replacing interupt 09h (the keyboard) it functions correctly, on keypress 'Memory messing' is outputted. But then nothing. Every keypress afterwards does nothing. I don't know if the system is crashing or if I'm missing something from my handler, here's the code:
jmp start
times 100 db 0 ; Cleared space for stack
start:
xor ax, ax
mov ax, start
sub ax, 80
mov sp, ax
mov al, 0x09 ; Interupt number
mov bl, 4
mul bl
mov bx, ax
xor ax, ax
mov es, ax
mov [es:bx], word prints ; My interupt handler
add bx, 2
mov [es:bx], word 0x00
bloader:
jmp bloader
prints:
cli
push ax
push bx
push si
mov si, msg ; Message to print
mov bl, 0x07
mov bh, 0x00
printnb:
lodsb ; Grab byte from message
cmp al, 0 ; End of message
je printf
mov ah, 0x0E
int 0x10 ; Print byte
jmp printnb
printf:
mov al, 0x20
out 0x20, al ; Inform interupt controller interupt has been handled
pop si
pop bx
pop ax
sti
iret ; Interupt return
msg db "Memory messing",0
times 510 - ($ - $$) db 0
dw 0xAA55
Solution
It's been a long while since I worked on dealing with keyboard interrupts, but I think what you're missing is actually handling the keyboard hardware so it'll clear the interrupt condition and be ready to generate another interrupt.
Something like:
in al, 60h ; Read input buffer
might be all it takes.
If I get a chance I'll see if I have any old notes or code lying around from way back when I wrote keyboard drivers.
OTHER TIPS
My guess (I've never written a keyboard interrupt handler) is that you also need to talk to the keyboard hardware, to retrieve the keystroke (otherwise the keyboard won't know when to generate a next interrupt).
I found another problem. If we set a new interrupt vector for an ISR with two seperate move-instructions, then it is possible that between this both mov-instructions an interrupt occur and then it get the address from a broken vector with one part of the old location and the other part of the new location of the ISR. But on this location there is no ISR, no instructions for an END of interrupt and also no iret instruction.
For to prevent such bad events we have to place a cli and sti around those move instructions for to set a new interrupt vector.
cli
mov [es:bx], word prints ; My interupt handler
mov [es:bx+2], word 0x00
sti
Dirk
This is only a wild guess, but maybe the problem is that you are calling int 10h from the int 9h handler. Try writing to screen memory directly (just increment the byte at 0b800h:0 and check to top left character on the screen). If it gets incremented for each keypress, then you shouldn't call int 10h from int 9h.