Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/svg/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 实模式下的自定义IRQ处理程序_Assembly_X86_Kernel_Nasm_Bootloader - Fatal编程技术网

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

Assembly 实模式下的自定义IRQ处理程序,assembly,x86,kernel,nasm,bootloader,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 ; R

我试图学习在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”打印到屏幕的部分在中断处理程序外部工作正常,因此这不是问题所在

我只能假设处理器从未进入中断处理程序——但我用
int0x69
显式地调用它


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

在x86中,您需要设置中断描述符表,以便中断正常工作。看一看,文件
interupt.s
desc_tables.c
将提供一些关于这方面的信息。这是我为教授x86和操作系统的基础知识而编写的一个小内核,因此您可以随意从中获取所需内容

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


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

我对您的
org
感到困惑。如果您不说,Nasm将默认为
org0
。这与加载ds的方式一致。但是
int\u prog
将被评估为。。。一些小值,而不是0x7C00+一些小值。在中断表地址的第二个字中放入
cs
。我们知道什么是
cs
?“可能”零。您已将
ds
设置为0x7C0。尝试使用
ds
而不是那里的
cs
。或者,将整件事作为
org0x7c00
进行,并将
ds
es
都设为零
pusha
popa
不保留段寄存器。由于您在ISR中更改了
es
,因此您可能还需要保存和恢复它(尽管我认为目前这不是一个问题)

好的,编辑:修复了“of”的拼写。而且。。。好的,你的密码在哪里?在0x7C00-这是您的BIOS(或假BIOS)加载它的位置。可寻址为段0偏移量0x7C00或段0x7C0偏移量0。很有可能您已经跳到了0:0x7C00,但0x7C0:0也可以工作,而且有传言说某款康柏Presario型号的BIOS就是这样做的。我们真的不应该指望它

那么你的中断服务程序的代码在哪里呢?在0:0x7Cxx或0x7C0:xx。您想将其中一个段:偏移组合放入中断向量表中(我们知道它在段0中-您完全正确地得到了这一部分)Jesus Ramos教授的建议是正确的,但他正在考虑稍后的过程中,当我们切换到保护模式时

因为您没有使用
org
指令,所以Nasm假定
org 0
,也就是说,它将地址计算为文件偏移量。如果您说
org0x7c00
Nasm将把地址计算为文件偏移量加上0x7C00。这就是
org
所做的。在您的例子中,Nasm将地址(地址的偏移部分)计算为“xx”。。。这就是你在IVT里放的东西。因此,在IVT的段部分(第二个单词),您需要0x7C0。0:xx将找不到您的代码。由于您已将已知值0x7C0放入
ds
,因此效果非常好


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

我的印象是,中断描述符表仅在保护模式下才需要。所以我需要在实模式下设置IDT?@VilhelmGray在实模式下IDT位于地址
0x0000-0x03FF
。您只需将一个实模式指针放在处理程序上(不确定64位上是否有8字节宽)。如果是实模式,则无需调用
lidt
。因为我使用的是64位处理器,所以线路
mov-dx,int\u-prog
可能是我问题的根源,因为
int_-prog
指针不适合16位
dx
寄存器?@VilhelmGray是的,从我记忆中的条目来看,有4个字节宽,所以你可以将其更改为
mov-edx,int_-prog
,这似乎是一个很有希望的线索,但我似乎没有任何效果。我尝试了
mov-edx,int\u-prog;mov[es:0x69*4],dx但似乎没有效果。我还尝试了
mov-edx,int\u-prog;mov[es:0x69*4],edx
没有用于cs的mov,但它也没有效果。我仍然怀疑在这段代码中发生了什么事情——也许我们有一个函数指针向后的布局,或者有什么效果。我执行了您建议的更改,现在它可以工作了,但是我很难理解您的解释。下面是它现在的样子:
movax,int\u prog;mov字[es:0x69*4],ax;mov[es:0x69*4+2],ds
。我的错误是因为当我应该使用在
ds
中加载的段地址时,所有符号都从
cs
寄存器偏移了吗?