Page 1 of 1

idt troubles....

Posted: Tue Jul 14, 2009 1:59 am
by brodeur235
This is frustrating as hell... Here's what I do:

(Please assume all my screen printing functions work; they do.)
1.) Set the screen colors to one color scheme.
2.) Set up IDT entry for interrupt 0
3.) Load the IDT descriptor with lidt
4.) Now I call int 0x00, but the ISR is not executed (it outputs a string that I'd see)
5.) Now I change the screen colors to another color scheme. This is never executed. The old color scheme is still in place. Int 0 never returned.

Again, assume the screen printing functions work such as changing the screen color (k_set_screen_colors) and printing a string (k_print_string_in_bounds) because they've been tested individually and work fine. The problem is setting up the IDT entry 0 to point to my ISR...

Here is the code the events above

Code: Select all

; setup screen colors
	xor eax,eax
	mov al,LIGHT_GREY
	shl al,4
	or al,BLACK
	push eax
	call k_set_screen_colors
	add esp,4
	
	call k_clear_screen
	
	; setup an ISR:
	; push DPL param
	xor eax,eax
	push eax
	; push selector param
	mov eax,0x00000008
	push eax
	; push offset of isr
	mov eax,((ISR_0-k_main)+KERNEL_OFFSET)   ;This IS the address of the ISR. This is NOT the problem.
	push eax
	; push interrupt #
	xor eax,eax
	push eax
	call k_install_isr
	add esp,0x00000010
	
	; load the idt
	lidt [idt_descriptor]
	
	; call an interrupt
	int 0x00
	
	; change screen colors
	xor eax,eax
	mov al,BLUE
	shl al,4
	or al,LIGHT_CYAN
	push eax
	call k_set_screen_colors
	add esp,4
And here is the function that sets up an IDT entry (I suspect the problem is here but I cannot find it...):

Code: Select all

; @param1 interrupt # (0-255)
; @param2 offset of ISR
; @param3 selecter (in GDT) for ISR
; @param4 DPL (ISR ring level)

%define NUM DWORD [ebp-16]
%define OFF DWORD [ebp-12]
%define SEL DWORD [ebp-8]
%define DPL DWORD [ebp-4]

k_install_isr:
	
	; setup stack frame
	push ebp
	mov ebp,esp
	
	; create space for local vars
	sub esp,0x00000010
	
	; get interrupt number
	mov eax,DWORD [ebp+8]
	mov NUM,eax
	
	; get offset
	mov eax,DWORD [ebp+12]
	mov OFF,eax
	
	; get selector
	mov eax,DWORD [ebp+16]
	mov SEL,eax
	
	; get DPL
	mov eax,DWORD [ebp+20]
	mov DPL,eax
	
	; calculate base address for interrupt entry
	xor eax,eax
	add eax,NUM
	imul eax,0x00000008
	add eax,idt_entries
	
	; put the lower word of the offset at the address
	xor ebx,ebx
	mov ebx,OFF
	mov WORD [ds:eax],bx
	add eax,0x00000002
	
	; put the selector at updated address
	xor ebx,ebx
	mov ebx,SEL
	mov WORD [ds:eax],bx
	add eax,0x00000002
	
	; put an empty byte at updated address
	xor ebx,ebx
	mov BYTE [ds:eax],bl
	inc eax
	
	; put the access byte at updated address
	xor ebx,ebx
	mov ebx,DPL
	shl bl,0x05
	or bl,10000000b ; bit mask turns on "present" bit
	or bl,00001110b ; bit mask makes int a 32 bit gate
	mov BYTE [ds:eax],bl
	inc eax
	
	; put the upper word of the offset at the updated address
	xor ebx,ebx
	mov ebx,OFF
	shr ebx,0x00000010
	mov WORD [ds:eax],bx
	
	; clean up stack frame
	mov esp,ebp
	pop ebp
	ret
Here is my ISR

Code: Select all

ISR_0:
	
	; save registers
	pusha
	push ds
	push es
	push fs
	push gs
	
	; setup stack frame
	push ebp
	mov ebp,esp
	
	; print a string
	push DWORD 25
	push DWORD 80
	push DWORD 1
	push DWORD 1
	push DWORD 1
	push DWORD 1
	xor eax,eax
	mov eax,((isr0_exec-k_main)+KERNEL_OFFSET)
	push eax
	call k_put_string_in_bounds
	add esp,0x0000001C
	
	; clean up stack frame
	mov esp,ebp
	pop ebp
	
	; load registers
	pop gs
	pop fs
	pop es
	pop ds
	popa
	
	iret
Finally, here is my IDT:

Code: Select all

idt_entries:
	
	; insert 256 zeroed out interrupt entries
	%rep 0x00000100
	dd 0x00000000
	dd 0x00000000
	%endrep
	
idt_descriptor:
	
	; 2 byte size
	dw (idt_descriptor-idt_entries-1)
	
	; 4 byte offset
	dd idt_entries
I realize that that's a ton, but I'm hoping someone might take the time to possibly skim through that and find and major flaws because I'm at a complete deadlock with this faulty code. I've been looking for an error for several hours. Your help is very much appreciated... I hope it saves me from this frustrating insanity,

Brodeur235

Re: idt troubles....

Posted: Tue Jul 14, 2009 6:40 am
by yemista
im not 100% sure, but isr0 is a divide by zero exception, and i dont think you can generate exceptions through hardware. if you didnt setup your idt correctly most likely it would triple fault on an interrupt so i dont think thats the case. it seems the handler just wont execute. You also seem to missing a 'sti' instruction

Re: idt troubles....

Posted: Tue Jul 14, 2009 10:43 am
by brodeur235
I'm not sure where I need to enable interrupts as I never disabled them, but I changed the interrupt call from:

Code: Select all

int 0x00
to:

Code: Select all

sti
	xor eax,eax
	xor ebx,ebx
	div bl
div bl seems to act the same way as directly calling int 0x00. If i comment it out, the screen changes color, but if I leave it, the intended isr is never executed, nor does it return allowing the screen colors to change...

Brodeur235

Re: idt troubles....

Posted: Tue Jul 14, 2009 11:57 am
by Creature
I'm not sure, but it could be possible that the hardware does a 'cli' instruction implicitely or you just need to explicitely execute an 'sti' instruction for interrupts to be enabled after you set up the IDT correctly.

Re: idt troubles....

Posted: Tue Jul 14, 2009 3:25 pm
by Firestryke31
If you're booting from GRUB, then that's where interrupts are disabled. This lets you set up the IDT without risking an int firing during the "transitional" state where things are not quite ready.

Re: idt troubles....

Posted: Thu Jul 16, 2009 4:14 pm
by frank
Disabling interrupts with cli doesn't affect software interrupts. You can still use int 0x?? with interrupts disabled.

Re: idt troubles....

Posted: Thu Jul 16, 2009 5:39 pm
by mathematician
Interrupts 0 thru 31 have been reserved by Intel, and some of them have been assigned a specific function, so you shouldn't really be using anything below int 20h for either hardware or software interrupts. int 0 is generated when you try to divide by 0. If you are using the 8259A controller, you should reprogram that, so that reserved interrupts are no longer being used. (Many moons ago, IBM thought in could ignore the reserved interrupts when is assigned 8 to the clock interrupt, 9 to the keyboard interrupt etc.)

Re: idt troubles....

Posted: Thu Jul 23, 2009 2:44 pm
by brodeur235
I realize this thread is a bit old but I didn't want to start a new one for the same issue. Since I last had this problem, I coded a function to dump memory, so I can see the address of any label I need, namely subroutines. Now I can directly enter an IDT entry without having to code a function to do this, which might have been the cause of the problems I was having before. Anyways, here's the deal:

I have an ISR at 0x0000B02F

Code: Select all

isr0:
	pusha
	push gs
	push fs
	push ds
	push es
	
	mov eax,0x000B8000
	mov BYTE [ds:eax],"A"
	
	pop es
	pop ds
	pop fs
	pop gs
	popa
	iret
I have a single entry in my IDT:

Code: Select all

; idt table
idt_entries:
	
	dw 0xB02F
	dw 0x0008
	dw 0x8E00
	dw 0x0000
	
idt_descriptor:
	
	; table size (2 bytes)
	dw (idt_descriptor - idt_entries - 1)
	
	; table offset (4 bytes)
	dd idt_entries
And I have the code that loads the idt register and call the interrupt:

Code: Select all

	; load IDT
	lidt [idt_descriptor]
	
	; try to call int 0 (div by 0 exception) directly
	int 0x00                                                                 ;IF I COMMENT OUT THIS LINE
	
	; try to provoke int 0 by dividing by 0
	xor ebx,ebx
	div bl                                                                 ;AND THIS LINE,
	
	mov eax,0x000B8002
	mov BYTE [ds:eax],"Q"                                       ; THEN Q IS OUTPUT AS EXPECTED
If I comment out "int 0x00" and "div bl" then Q is output at (2,1) as expected. However, If I leave either of those lines uncommented, Q is never output and neither is A as is expected because that's what the ISR is supposed to do.

In short, I can trigger the exception, but the code in my ISR is not executing or returning for some reason...

This is much less code to look over and hopefully a mistake can be spotted because I still can't find one,

Brodeu235

Re: idt troubles....

Posted: Thu Jul 23, 2009 6:13 pm
by geppyfx
i can't see anything wrong with the code at the moment but better way to test whenever isr0 gets executed or not is to add 'jmp $' to the isr0

Code: Select all

isr0:
   pusha
   push gs
   push fs
   push ds
   push es
   
   mov eax,0x000B8000
   mov BYTE [ds:eax],"A"
back:
   jmp back
after 'A' is displayed you can proceed with testing the return from interrupt handler
and since you will not be returning from isr0 right now, its better to remove all stack operations(pusha,push)

Re: idt troubles....

Posted: Thu Jul 23, 2009 11:55 pm
by brodeur235
I have checked repeatedly and everything is set exactly as I set it up. Nothing is out of place, except for the inexplicable fact that the ISR isn't executing... I printed a debug image and edited it in photoshop real quick so you could see exactly how I have things set up and catch any possible errors. I'm pulling my hair out over this... Here's the image:

Image

Of course, the values are stored in little endian, so to quickly translate that:

ISR OFFSET: 0x0000B0C2

IDT ENTRIES OFFSET: 0x0000B0F5
values at this offset are: 0x0000, 0x8E00, 0x0008, 0xB0C2

IDT DESCRIPTOR OFFSET: 0x0000B0FD
values at this offset are: 0x0007, 0x0000B0F5

These all look 100% correct to me, but when I trigger int 0x00, the ISR is still not executing. .. .. ?!

Brodeur235

EDIT: Thanks for the reply geppyfx, I took your advice but unfortunately I still can't manage to generate any productive results.

Re: idt troubles....

Posted: Fri Jul 31, 2009 4:20 pm
by Combuster
You are setting up an IVT rather than an IDT. It obviously doesn't work when you try to use the real mode interrupt mechanism in protected mode...