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

标签 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 特定设置?

最佳答案

我对你们的组织感到困惑。如果您不指定,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 中 - 您完全正确地理解了该部分)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/

相关文章:

assembly - 汇编代码帮助

assembly - 操作系统如何阻止程序访问内存?

c++ - 线程和上下文切换 C++

assembly - 从 FAT 软盘镜像读取第二阶段引导加载程序

CFQ理解 `cfq_cfq_cfqq_slice_new(cfqq)`

kernel - 用户/内核模式和保护/实模式有什么区别?他们是一样的吗?

c++ - MSVC下的奇优化问题

c++ - gcc 中的 Intel 风格内联汇编

linux - 需要清理缓冲区吗? x86 Linux 汇编器

c++ - IPV6双栈模式检查ipv6内核模块是否加载