我正在尝试学习 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 特定设置?
最佳答案
我对你们的组织
感到困惑。如果您不指定,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 中 - 您完全正确地理解了该部分)Jesus Ramos 教授的建议是正确的,但他正在考虑稍后的过程,当我们已切换到保护模式。
因为您没有使用 org
指令,Nasm 假定 org 0
,也就是说,它将地址计算为文件偏移量。如果您说 org 0x7C00
Nasm 会将地址计算为文件偏移量加上 0x7C00。这就是 org
所做的。就您而言,Nasm 已将地址(地址的偏移部分)评估为“xx”...这就是您放入 IVT 中的内容。因此,在 IVT 的段部分(第二个字)中,您需要 0x7C0。 0:xx 不会找到您的代码。由于您已将已知值 0x7C0 放入 ds
中,因此效果很好。
如果我没有回答您的问题,请再问...
关于assembly - 实模式下的自定义 IRQ 处理程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18879479/