我正在尝试在 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特定的设置?
答案 0 :(得分:2)
我对你的org
感到困惑。如果你不说,Nasm将默认为org 0
。这与您加载ds
的方式一致。但是int_prog
将被评估为......一些小值,而不是0x7C00 +一些小值。您将cs
放在中断表地址的第二个字中。我们知道cs
是什么吗? “可能”为零。您已将ds
设置为0x7C0。尝试在那里使用ds
代替cs
。或者,将整个事情视为org 0x7C00
并使ds
和es
都为零。 pusha
和popa
不保留段寄存器。由于您在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.s
和desc_tables.c
会提供一些相关信息。这是我为教授x86和操作系统基础知识而编写的一个小内核,所以随时可以随心所欲地抓取它。
基本上你需要设置IDT(中断描述符表)。在此之前,您必须执行一系列指令来重新映射IRQ表(一些outportb
指令和正确的值),用ID填充IDT,最后发出lidt
指令将描述符表加载到适当的地方。
在实模式下,IDT位于地址0x0000 - 0x03FF
中,由4个字节的条目组成(不确定64位上的8个字节,但这意味着地址范围的上限为2048而不是1024) 。只需将实模式指针写入表中的正确条目(它看起来就像你正在做的那样)。由于使用dx
vs edx