为什么在qemu-system-x86_64上 BIOS 中断 8 (计时器) 失效

3

我认为BIOS中断8(定时器)应该每秒钟出现18.2次,但在qemu上却没有。请看下面的例子:

$ cat c.asm

init:
    .segments:
        mov ax, 0x07C0
        mov ds, ax
        mov ax, 0
        mov fs, ax
    .interrupt:
        mov [fs:0x08*4], word timer
        mov [fs:0x08*4+2], ds

main:
    hlt
    jmp main

timer:
    mov ah, 0x0e
    mov al, 0x41
    int 0x10
    iret

times 510-($-$$) db 0
dw 0xaa55

$ nasm -f bin c.asm -o c.bin && qemu-system-x86_64 c.bin

Qemu窗口出现,只显示一个"A",而不是连续出现。

如果我希望不断地收到中断8,那么我的代码有什么问题。

我使用的是nasm 1.14.02、qemu 4.2.1和ubuntu 20.04。


2
你尝试过使用调试器吗?QEMU可以让你附加GDB,但对于分段实模式,你最好使用BOCHS的内置调试器。此外,通常你应该保存/恢复在中断处理程序中修改的任何寄存器;这至少会破坏AX寄存器。 - Peter Cordes
1个回答

4
重要更改是向端口20h发送中断结束信号,以便重复显示“ A”。如果您使用中断1Ch或链接到另一个中断08h处理程序,则不需要这样做。但是,如果完全替换中断08h处理程序,则需要这样做。PIC在先前的IRQ#0获得EOI之前不会发送另一个IRQ#0。因此,我能够重现您的问题。
我所做的其他更改是确保在进入main循环之前设置中断标志(使用sti指令),并跨中断08h处理程序保存所有寄存器(如果您的代码是计算机上唯一运行的内容,则可选择不保存)。
init:
    .segments:
        mov ax, 0x07C0
        mov ds, ax
        mov ax, 0
        mov fs, ax
    .interrupt:
        mov [fs:0x08*4], word timer
        mov [fs:0x08*4+2], ds

        sti
main:
    hlt
    jmp main

timer:
        push ax
        push bx
        push bp
    mov ah, 0x0e
    mov al, 0x41
    int 0x10
        mov al, 20h
        out 20h, al
        pop bp
        pop bx
        pop ax
    iret

times 510-($-$$) db 0
dw 0xaa55

按如下方式运行:

$ nasm test.asm
$ timeout 10 qemu-system-x86_64 test -curses

2
@Sep Roland:在中断列表中,bp被一些有缺陷的实现标记为已修改,请参见http://www.ctyme.com/intr/rb-0106.htm -- bx只是此服务的另一个输入,但可能不会被修改。为了安全起见。 - ecm

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接