实模式,中断向量替换崩溃

时间:2022-03-12 13:05:05

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:

我正在尝试更多地了解系统如何真正在顶部所有漂亮的图形下工作。所以我目前正在使用BIOS在启动时加载的512字节内存,在我猜的时刻真的不能称之为引导加载程序。无论如何,我正在替换一个中断向量,但有问题。更换中断09h(键盘)后,它正常工作,在按键上输出“Memory messing”。但没什么。之后的每一个按键都什么都不做。我不知道系统是否崩溃或者我是否遗漏了处理程序中的内容,这里是代码:

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

4 个解决方案

#1


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.

如果我有机会,当我编写键盘驱动程序时,我会看到我是否有任何旧笔记或代码。

#2


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).

我的猜测(我从未编写过键盘中断处理程序)是你还需要与键盘硬件通信,以检索击键(否则键盘将不知道何时生成下一个中断)。

#3


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.

我发现了另一个问题。如果我们为具有两个单独的移动指令的ISR设置一个新的中断向量,则可能在这两个mov指令之间发生中断,然后它从具有旧位置的一部分的断开向量中获取地址ISR新位置的其他部分。但是在这个位置上没有ISR,没有END中断指令,也没有iret指令。

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和sti来设置一个新的中断向量。

cli
mov [es:bx], word prints ; My interupt handler
mov [es:bx+2], word 0x00
sti

Dirk

#4


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.

这只是一个疯狂的猜测,但问题可能是你从int 9h处理程序调用int 10h。尝试直接写入屏幕内存(只需将字节增加到0b800h:0并检查屏幕左上角的字符)。如果每个按键增加,那么你不应该从int 9h调用int 10h。

#1


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.

如果我有机会,当我编写键盘驱动程序时,我会看到我是否有任何旧笔记或代码。

#2


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).

我的猜测(我从未编写过键盘中断处理程序)是你还需要与键盘硬件通信,以检索击键(否则键盘将不知道何时生成下一个中断)。

#3


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.

我发现了另一个问题。如果我们为具有两个单独的移动指令的ISR设置一个新的中断向量,则可能在这两个mov指令之间发生中断,然后它从具有旧位置的一部分的断开向量中获取地址ISR新位置的其他部分。但是在这个位置上没有ISR,没有END中断指令,也没有iret指令。

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和sti来设置一个新的中断向量。

cli
mov [es:bx], word prints ; My interupt handler
mov [es:bx+2], word 0x00
sti

Dirk

#4


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.

这只是一个疯狂的猜测,但问题可能是你从int 9h处理程序调用int 10h。尝试直接写入屏幕内存(只需将字节增加到0b800h:0并检查屏幕左上角的字符)。如果每个按键增加,那么你不应该从int 9h调用int 10h。