IDT and ISRs

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
Tolga

IDT and ISRs

Post by Tolga »

Hi. I saw a tutorial in osdever.net about interrupts. In document 3, author creating ISR codes as:

isr0:
pusha
push ds
...

...
pop ds
popa
iret

after this, creating idt items. But all items are same. I don't understand that when interrupt 0 triggered, how the processor understand where is the interrupt 0 code? Is the document wrong? Thanks. ;)
bkilgore

Re:IDT and ISRs

Post by bkilgore »

Code: Select all

From what I can see from part3 of that example, he's not using individual isr handlers for each interrupts. The first and last dw for each interrupt together define the offset in the code segment, which he is setting to 0x200000 for all of them. This means that all of those interrupts will cause the same ISR to run. 

Typically, you will want to change this offset to be the offset of your ISR that you want executed for a particular interrupt, such as (modified from the FAQ):
%define BASE_OF_SECTION SOME_CONSTANT_YOU_SHOULD_KNOW
isr0:
iret

isr1:
; do soemthing else...
iret

idt0 dw (BASE_OF_SECTION isr0 - $$) & 0xFFFF
dw 0x10
dw 0x8E00
dw (BASE_OF_SECTION isr0 - $$) >> 16

Code: Select all


idt1 dw (BASE_OF_SECTION isr1 - $$) & 0xFFFF
           dw 0x10
           dw 0x8E00
           dw (BASE_OF_SECTION isr1 - $$) >> 16
Tolga

Re:IDT and ISRs

Post by Tolga »

Hmm. You are saying that;

isr0 base address = idt0 base address
isr1 base address = idt1 base address
isr2 base address = idt2 base address
...
...
...
Midas
Member
Member
Posts: 140
Joined: Sat Jun 24, 2006 4:40 pm
Location: Falkirk, Scotland
Contact:

Re:IDT and ISRs

Post by Midas »

Each 8-byte entry in the IDT (helpfully ignoring the fact that it's encoded so as to be a nightmare (why is it?)) has a section for the base address of the handler for that interrupt.

When the CPU receives an interrupt, it does:

INT Number * 8 to find the IDT entry for that INT, then decodes the base address and uses that to handle the interrupt.
Regards,
Angus [Óengus] 'Midas' Lepper
bkilgore

Re:IDT and ISRs

Post by bkilgore »

Tolga wrote: Hmm. You are saying that;

isr0 base address = idt0 base address
isr1 base address = idt1 base address
isr2 base address = idt2 base address
...
...
...
I'm not sure exactly what you mean, but you want:

"offset" stored in idt0 = offset of isr0
"offset" stored in idt1 = offset of isr1
etc..

Unfortunately the offset is stored split up into two chunks, so you have to wave your hands a little to get it to put the right address in there, but thats the idea. You are saying in each entry in the IDT what code segment to use and what offset in that code segment to jump to when the associated interrupt occurs.
paulbarker

Re:IDT and ISRs

Post by paulbarker »

The best way of doing this is via a table of handlers, if you can deal with the tentacles:

handlers.S

The above is written for GAS but it is simpler with NASM's %rep construct.

Now the setup code for the IDT is simply:

Code: Select all

void i_interrupt_gate(uint nr,
                      uint16_t selector,
                      uint32_t addr,
                      uint dpl,
                      bool is32bit);

Code: Select all

    uint addr = (uint) &g_handlers;

    /* load interrupt handlers */
    for (i = 0; i < NR_IDT_ENTRIES; i++) {
        i_interrupt_gate(i, KERNEL_CS, addr, 0, true);

        addr += HANDLER_SIZE;
    }
Dex4u

Re:IDT and ISRs

Post by Dex4u »

Mine is more like this:

Code: Select all

;====================================================;
;  Idt.                                              ;
;====================================================;
idt:

;0 interrupt 0h
???dw div_error??????           ; div error
???dw sys_code
???db 0
???db sys_interrupt
???dw 0

;1 interrupt 1h
???dw debug_exception???           ; debug exception
???dw sys_code
???db 0
???db sys_interrupt
???dw 0

;2 interrupt 2h
???dw nmi_interrupt???           ; non maskable interrupt
???dw sys_code
???db 0
???db sys_interrupt
???dw 0

;3 interrupt 3h
???dw int3_trap??????           ; int3 trap
???dw sys_code
???db 0
???db sys_interrupt
???dw 0

;4 interrupt 4h
???dw into_trap??????           ; into trap
???dw sys_code
???db 0
???db sys_interrupt
???dw 0

;5 interrupt 5h
???dw bound_trap??????           ; bound trap
???dw sys_code
???db 0
???db sys_interrupt
???dw 0

;6 interrupt 6h
???dw invalid_instruction???           ; invalid instruction
???dw sys_code
???db 0
???db sys_interrupt
???dw 0
; More here ...................................................
To point to these:

Code: Select all

 ;----------------------------------------------------;
 ;  unhandled int.                                    ;
 ;----------------------------------------------------;

unhandled_int:
        pushad
        push  es
        push  ds
        mov   ax,8h
???mov   es,ax
???mov   byte [es:0xB809E], "U"
        pop   ds
        pop   es
        popad
???iret
 ;----------------------------------------------------;
 ;  nmi interrupt.                                    ;
 ;----------------------------------------------------;

nmi_interrupt:
        pushad
        push  es
        push  ds
        mov   ax,8h
???mov   es,ax
???mov   byte [es:0xB809E], "N"
???jmp   $
        pop   ds
        pop   es
        popad
        iret

 ;----------------------------------------------------;
 ;                                                    ;
 ;----------------------------------------------------;

page_fault:
        pushad
        push  es
        push  ds
        mov ax,8h
???mov es,ax
???mov byte [es:0xB809C], "P"
        pop   ds
        pop   es
        popad
???iret

 ;----------------------------------------------------;
 ;                                                    ;
 ;----------------------------------------------------;

div_error:
        pushad
        push  es
        push  ds
        mov ax,8h
???mov es,ax
???mov byte [es:0xB809C], "D"
        pop   ds
        pop   es
        popad
???iret
 ;----------------------------------------------------;
 ;                                                    ;
 ;----------------------------------------------------;

debug_exception:
        pushad
        push  es
        push  ds
        mov ax,8h
???mov es,ax
???mov byte [es:0xB809C], "d"
        pop   ds
        pop   es
        popad
???iret
 ;----------------------------------------------------;
 ;                                                    ;
 ;----------------------------------------------------;

int3_trap:
        pushad
        push  es
        push  ds
        mov ax,8h
???mov es,ax
???mov byte [es:0xB809C], "3"
        pop   ds
        pop   es
        popad
???iret
 ;----------------------------------------------------;
 ;                                                    ;
 ;----------------------------------------------------;

into_trap:
        pushad
        push  es
        push  ds
        mov ax,8h
???mov es,ax
???mov byte [es:0xB809C], "O"
        pop   ds
        pop   es
        popad
???iret
This is from Dex4u full source available here:
http://www.dex4u.com/download.htm

To answer your ?, it must times the int number by 8, that why it start at 0 .
Post Reply