idt troubles....

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
brodeur235
Member
Member
Posts: 86
Joined: Sat Jun 06, 2009 11:55 am

idt troubles....

Post 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
User avatar
yemista
Member
Member
Posts: 299
Joined: Fri Dec 26, 2008 12:31 pm
Location: Boston
Contact:

Re: idt troubles....

Post 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
brodeur235
Member
Member
Posts: 86
Joined: Sat Jun 06, 2009 11:55 am

Re: idt troubles....

Post 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
User avatar
Creature
Member
Member
Posts: 548
Joined: Sat Dec 27, 2008 2:34 pm
Location: Belgium

Re: idt troubles....

Post 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.
When the chance of succeeding is 99%, there is still a 50% chance of that success happening.
User avatar
Firestryke31
Member
Member
Posts: 550
Joined: Sat Nov 29, 2008 1:07 pm
Location: Throw a dart at central Texas
Contact:

Re: idt troubles....

Post 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.
Owner of Fawkes Software.
Wierd Al wrote: You think your Commodore 64 is really neato,
What kind of chip you got in there, a Dorito?
frank
Member
Member
Posts: 729
Joined: Sat Dec 30, 2006 2:31 pm
Location: East Coast, USA

Re: idt troubles....

Post by frank »

Disabling interrupts with cli doesn't affect software interrupts. You can still use int 0x?? with interrupts disabled.
User avatar
mathematician
Member
Member
Posts: 437
Joined: Fri Dec 15, 2006 5:26 pm
Location: Church Stretton Uk

Re: idt troubles....

Post 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.)
The continuous image of a connected set is connected.
brodeur235
Member
Member
Posts: 86
Joined: Sat Jun 06, 2009 11:55 am

Re: idt troubles....

Post 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
geppyfx
Member
Member
Posts: 87
Joined: Tue Apr 28, 2009 4:58 pm

Re: idt troubles....

Post 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)
brodeur235
Member
Member
Posts: 86
Joined: Sat Jun 06, 2009 11:55 am

Re: idt troubles....

Post 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.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: idt troubles....

Post 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...
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
Post Reply