How to set up an IDT

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
User avatar
XCHG
Member
Member
Posts: 416
Joined: Sat Nov 25, 2006 3:55 am
Location: Wisconsin
Contact:

How to set up an IDT

Post by XCHG »

It has been a few days since I’ve started searching for a working example of an IDT and unfortunately I haven’t yet been able to find one written in NASM (with its bloated syntax). I have only set up my GDT and switched to PM with a very small kernel which only clears the screen. I would really appreciate it if somebody could give me an example that for example sets up the IDT for INT 0x10, written in NASM. Thanks in advance guys.
Ready4Dis
Member
Member
Posts: 571
Joined: Sat Nov 18, 2006 9:11 am

Re: How to set up an IDT

Post by Ready4Dis »

XCHG wrote:It has been a few days since I’ve started searching for a working example of an IDT and unfortunately I haven’t yet been able to find one written in NASM (with its bloated syntax). I have only set up my GDT and switched to PM with a very small kernel which only clears the screen. I would really appreciate it if somebody could give me an example that for example sets up the IDT for INT 0x10, written in NASM. Thanks in advance guys.
int 0x10 in PM is not the same as int 0x10 in real mode, just to give you a heads up. You have to fill in all interrupts in pmode, you can't just call them or it will triple fault, you must initialize them before use, and give them an interrupt routine/handler. If you are looking to use int 0x10 (video interrupt in real mode), you must be in real mode (*or equivelant, ala virtual x86 mode).
Otter
Member
Member
Posts: 75
Joined: Sun Dec 31, 2006 11:56 am
Location: Germany

Post by Otter »

The simplest way is to use a hardcoded idt, for expample:

Code: Select all

%macro idtentry 2
dw %1 & 0xFFFF ; Low-Word of Offset
dw %2          ; Code-Segment-Selector
dw 0x8e00
dw %1 >> 16
%endmacro

idt:
times 0x10 dd 0,0 ; the first 0x10 entries
idtentry __myInt10h,0x08 ; dunno what your code segment selector is, assuming 0x08
idt_end:

idtR:
dw idt_end-idt-1
dd idt

__myInt10h:
; Your code for int10h
iret
You can load this IDT by "lidt [idtR]"
User avatar
XCHG
Member
Member
Posts: 416
Joined: Sat Nov 25, 2006 3:55 am
Location: Wisconsin
Contact:

Post by XCHG »

Thank you so much guys. I'm starting to *really* like this community. I appreciate it.
User avatar
XCHG
Member
Member
Posts: 416
Joined: Sat Nov 25, 2006 3:55 am
Location: Wisconsin
Contact:

How to set up an IDT

Post by XCHG »

I don’t think my IDT is working correctly. Well the first problem is that NASM complains when I use &, >>, << and etc with my trap-handler’s offset. For example, this is what I had in mind which however doesn’t work:

Code: Select all

  Int10Handler:
    ;~
    IRET
  ; -----------------------------
  ALIGN 8, NOP
  IDT:
    TIMES   0x10 DD 0 , 0
    DW      Int10Handler & 0xFFFF
    DW      0x0008
    DW      0x8E00
    DW      (Int10Handler >> 0x10) & 0xFFFF
  IDT_END:
  ;------------------------------
  IDTR:
    DW (IDT_END - IDT) - 1
    DD IDT

I also retrieved the offset to the “Int10Handler” procedure and created a “__WriteInt” procedure to retrieve its address manually. I then put the high and the low order words of the “Int10Handler” procedure in the corresponding descriptor but the system crashed and rebooted as soon as I enabled the interrupts. Does anybody have any idea how I can first fix the problem with NASM operators and then fix my IDT?
Otter
Member
Member
Posts: 75
Joined: Sun Dec 31, 2006 11:56 am
Location: Germany

Post by Otter »

You cannot use operators like & and << with offsets which are not known at assemble time. If you use "nasm -fbin" they are known, but if you use elf as target they are filled in by the linker. So I'm afraid you have to set up the idt in run time ...

[edit]A simple example: (untested)

Code: Select all

IDT:
times 0x10 dd 0,0
dd Int10Handler,Int10Handler
IDT_END:

; IDT is not valid yet ... this code should correct it
setupIdt:
mov ecx,(IDT_END - IDT ) / 8
mov edx,IDT
setupIdt_loop:
cmp dword[edx],0
jz  setupIdt_loopNext
mov dword[edx+2],0x8E000008
setupIdt_loopNext:
add edx,8
loop setupIdt_loop
I use a simple trick: You see the template for the idt entry, which is: "dd Int10Handler,Int10Handler" ... you can see that the lower word and the high word of the Idt10Handler are in the correct fields ... only the code segment selector 0x0008 and the 0x8e00 have to be added[/edit]
User avatar
XCHG
Member
Member
Posts: 416
Joined: Sat Nov 25, 2006 3:55 am
Location: Wisconsin
Contact:

Post by XCHG »

Oh so basically I have to fill the IDT at run-time, is that close on being on the money? I should then be able to enable the interrupts with STI right? I am going to try it now. Thank you so much.
User avatar
XCHG
Member
Member
Posts: 416
Joined: Sat Nov 25, 2006 3:55 am
Location: Wisconsin
Contact:

Post by XCHG »

Okay I got the IDT working but there is something that I don't understand.

I was looking to set up the IDT to use it for Traps (Software Interrupts) and without setting the Interrupt Flag, I can still use the INT instruction.

Here is how I set the IDT:

Code: Select all

  Int10Handler:            ; Dummy INT 0x10 Handler
    MOV     EBX , VIDEOSEGMENT
    ADD     EBX , DWORD PTR [VideoCursor]
    MOV     WORD PTR [EBX] , 0x0F41
    IRET                   ; Return from the Trap
  ; -----------------------------
  ALIGN 8, NOP             ; Align the IDT on QWORD boundary
  IDT:                     ; Beginning of the IDT
    TIMES   0x10 DD 0 , 0  ; 16 empty descriptors
    DW      0x0000         ; Low order Word of the handler
    DW      0x0008         ; Code segment selector in GDT
    DW      0x8F00         ; Trap Gate
    DW      0x0000         ; High order Word of the handler
  IDT_END:                 ; End of the IDT
  ;------------------------------
  IDTR:                    ; Limits of the IDT
    DW (IDT_END - IDT) - 1 ; Integer multiple of 8 minus 1
    DD IDT                 ; Starting point of the IDT
In the kernel, I tried set the Low and the High Order Word of the Trap handler like this:

Code: Select all

  %IDEFINE EMPTYSLOTCOUNT 0x10
  %IDEFINE IDT_ENTRY_LEN  0x08
  %IDEFINE BYTESTOSKIP (EMPTYSLOTCOUNT * IDT_ENTRY_LEN)
  ; ---------------------------
  LEA     EBX , [IDT + BYTESTOSKIP]   ; EA of the last descriptor
  MOV     EAX , Int10Handler          ; Get the offset of the handler
  MOV     WORD PTR [EBX] , AX         ; Put its Low Order Word in IDT[0x10]
  SHR     EAX , 16                    ; Get the High Order Word of the handler
  MOV     WORD PTR [EBX+06h] , AX     ; Put it at the 4th WORD in IDT[0x10]
  ; --------------------------
  LIDT    [IDTR]                      ; Load the Interrupt Descriptor Table
  ;STI                                 ; Enable Interrupts - BOOM !
  INT     10h
I have commented the STI instruction but it still works. My question is: can we have a Trap and an Interrupt handler in the range 0x00 ... 0xFF? I mean how can we distinguish between them? Let's say I create the IDT to handle IRQs and other Harware Interrupts and now I want to create the IDT for software interrupts? What will happen? What should I do? Who am I? Who are you?

P.S: Thank you for your help.
SpooK
Member
Member
Posts: 260
Joined: Sun Jun 18, 2006 7:21 pm

Post by SpooK »

XCHG wrote: I have commented the STI instruction but it still works. My question is: can we have a Trap and an Interrupt handler in the range 0x00 ... 0xFF? I mean how can we distinguish between them? Let's say I create the IDT to handle IRQs and other Harware Interrupts and now I want to create the IDT for software interrupts? What will happen? What should I do? Who am I? Who are you?
AFAIK, CLI/STI only applies to Interrupts (i.e. hardware generated interrupts). Software exceptions (or simply "Exceptions") will still be executed.

Also, if I am not mistaken, all Interrupts have Ring-0 privilege by design.

Trap gates are dependent on the TSS, which makes it more geared towards people who wish to utilize the Segmentation memory model (if you understand the depth/complexity of this design already).

You can simply make every IDT entry an "Interrupt Gate" and setup proper gate permissions (DPL). If you are using Ring-0 only, then you have very little you can do in protecting yourself against other Ring-0 code anyhow. If you are using the common Ring-0/Ring-3 segregation, then you are already set by the existence/use of the DPL. Just plug n' play :P

If you are trying to overload interrupts (make one interrupt do two things, depending on if it is hardware or software), then I have no advise for you as I haven't tried that... nor do I think it is a good idea.

HtH.
Last edited by SpooK on Sun Feb 04, 2007 4:23 am, edited 1 time in total.
Otter
Member
Member
Posts: 75
Joined: Sun Dec 31, 2006 11:56 am
Location: Germany

Post by Otter »

Yes, if you only want to call your itn 10h manually, sti is not necessary. But if you don't want to you should add "push ebx / pop ebx" to your handler ...
User avatar
XCHG
Member
Member
Posts: 416
Joined: Sat Nov 25, 2006 3:55 am
Location: Wisconsin
Contact:

Post by XCHG »

Great! Thank you both for your help. Appreciations,

P.S: Spook? Good to see a familiar face in here!
SpooK
Member
Member
Posts: 260
Joined: Sun Jun 18, 2006 7:21 pm

Post by SpooK »

I thought something looked funny about this post... looks like I mixed up my technical jargon :P

Interrupts are hardware generated.

Exceptions are software generated.

I have modified the post to reflect the correct usage of such terms ;)
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Post by Candy »

SpooK wrote:I thought something looked funny about this post... looks like I mixed up my technical jargon :P

Interrupts are hardware generated.

Exceptions are software generated.

I have modified the post to reflect the correct usage of such terms ;)
Physical interrupts (as in, IRQ, interrupt line etc) are hardware generated. Exceptions is your processor freaking out because you did something that you shouldn't have in your software. Software interrupts are people doing "INT 0x25".
Post Reply