实模式下的自定义IRQ处理程序

时间:2013-09-18 18:18:34

标签: assembly x86 kernel nasm bootloader

我正在尝试在 64位Intel Atom 处理器( x86_64 )上学习基本的操作系统开发。我无法让中断处理程序工作 - 我认为它没有在中断向量表中正确注册。

以下是我完全加载到引导扇区的代码:

; The code in the boot sector of the disk is loaded by the BIOS at 0000:7c00 
mov ax, 0x07c0
mov ds, ax

; Set es register to 0x0000
xor ax, ax
mov es, ax

; Register IRQ 0x69 handler in the Interrupt Vector Table
cli
mov dx, int_prog
mov [es:0x69*4], dx
mov ax, cs
mov [es:0x69*4+2], ax
sti

; Call interrupt handler for IRQ 0x69
nop
int 0x69

; Busy loop to allow time for human to look at screen
hang:
    jmp hang

; Interrupt Handler
int_prog:
    pusha

    ; Print red 'A' to screen
    mov ax, 0xB800
    mov es, ax
    mov [es:0], word 0x441

    popa
    iret

; Pad with zeroes and add signature at end
times 510-($-$$) db 0
dw 0x55AA

我期待屏幕左下角出现红色“A”,但没有任何内容出现。将红色“A”打印到屏幕的部分在中断处理程序之外工作正常,所以这不是问题。

我只能假设处理器从不进入中断处理程序 - 但我明确地用int 0x69调用它。

我的代码中是否缺少某种 x86特定的设置?

2 个答案:

答案 0 :(得分:2)

我对你的org感到困惑。如果你不说,Nasm将默认为org 0。这与您加载ds的方式一致。但是int_prog将被评估为......一些小值,而不是0x7C00 +一些小值。您将cs放在中断表地址的第二个字中。我们知道cs是什么吗? “可能”为零。您已将ds设置为0x7C0。尝试在那里使用ds代替cs。或者,将整个事情视为org 0x7C00并使dses都为零。 pushapopa不保留段寄存器。由于您在ISR中更改es,您可能还想保存并恢复它(尽管我认为这不是当前的问题)。

好的,编辑:修正了“of”的拼写。而且......好吧,你的代码在哪里?在0x7C00 - 这是你的BIOS(或假的BIOS)加载它。这可以解决为段0偏移0x7C00,或段0x7C0偏移0.这是一个很好的赌注,你已经跳到0:0x7C00,但0x7C0:0也可以工作,并且有传言说某个Compaq中的BIOS Presario模型就这样做了。我们真的不应该指望它。

那么您的中断服务程序的代码在哪里?在0:0x7Cxx或在0x7C0:xx。你想把这些段中的一个:偏移组合放入你的中断向量表(我们知道在第0段 - 你得到的那部分完全正确)耶稣拉莫斯教授的建议是正确的,但他在考虑后期的过程中我们已切换到保护模式。

因为您没有使用org指令,所以Nasm假设org 0,即它将地址评估为文件偏移量。如果您说org 0x7C00 Nasm会将地址评估为文件偏移量加上0x7C00。这就是org的作用。在你的情况下,Nasm已经将地址(地址的偏移部分)评估为“xx”......这就是你在IVT中的内容。因此,在IVT的段部分(第二个字)中,您需要0x7C0。 0:xx无法找到您的代码。由于您已将已知值0x7C0放在ds中,因此效果非常好。

如果我没有回答您的问题,请再次询问......

答案 1 :(得分:1)

在x86中,您需要设置中断描述符表,以便中断工作。看一下https://github.com/jesus-ramos/not-a-good-os/tree/master/kernel,文件interupt.sdesc_tables.c会提供一些相关信息。这是我为教授x86和操作系统基础知识而编写的一个小内核,所以随时可以随心所欲地抓取它。

基本上你需要设置IDT(中断描述符表)。在此之前,您必须执行一系列指令来重新映射IRQ表(一些outportb指令和正确的值),用ID填充IDT,最后发出lidt指令将描述符表加载到适当的地方。

在实模式下,IDT位于地址0x0000 - 0x03FF中,由4个字节的条目组成(不确定64位上的8个字节,但这意味着地址范围的上限为2048而不是1024) 。只需将实模式指针写入表中的正确条目(它看起来就像你正在做的那样)。由于使用dx vs edx

,问题可能是因为输入的值不正确