IDT in assembly

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.
Elja98
Posts: 15
Joined: Fri Aug 16, 2013 1:38 pm

IDT in assembly

Post by Elja98 »

Hi,

I'm busy handling some exceptions but unfortunately I still don't have any success with it. I'm installing a IDT and have a default exception handler, the only problem is: the handler is never called. This is my code, I'm in 32bits pure assembly:

Code: Select all

Initialize_IDT:
	pusha
	mov	ecx, 0					
.loop:
	cmp	ecx, 256				;Did we set every decriptor?
	je	.done		
	
	mov	eax, 8				;Location of descriptor = IDT_start + (NumberOfInterrupt * 8) 
	mul	ecx
	mov	ebx, IDT_start
	add	eax, ebx				;EAX is location to store handler
	
	mov	edx, handler			
	mov	ebx, edx	
	and	edx, 0xFFFF			;EDX = LoBase
	shr	ebx, 16				;EBX = HiBase
	
	mov	WORD [eax], dx		             ;Store the LoBase
	mov	WORD [eax+2], 0x8		;Set the selector
	mov	BYTE [eax+4], 0			;Reserved
	mov	BYTE [eax+5], 10001110b		;01110 = 32bits, 00 = ring 0, 1 = set
	mov	WORD [eax+6], bx			;Store the HiBase

	inc	ecx				;Point to next decriptor
	jmp	.loop				;Loop
	
.done:
	lidt	[idtr]				;Install the IDT
	popa
	ret
	

handler:
	mov	DWORD [gs:0xB8000], ') : '		;Print a sad smiley to the screen
	cli
	hlt
	
	
IDT_start:
	times	2048	db	0		;IDT buffer
IDT_end:

idtr:
dw	IDT_end - IDT_start - 1
dd	IDT_start
This is my code to initialize the IDT and make every descriptor point to the same handler (Just for simplicity for now). To test the code I just call the Initialize_IDT function and int 15h.

Thanks in advance!
h0bby1
Member
Member
Posts: 240
Joined: Wed Aug 21, 2013 7:08 am

Re: IDT in assembly

Post by h0bby1 »

my code looks like that

Code: Select all

%define FLAG_PRESENT  0x8000
%define FLAG_INT_CALL 0x0E00

%macro idt_init_int 2

lea eax   			,[interupt_%1]
mov [%2+0]  	    ,ax

mov word [%2+2]		,0x0008
mov word [%2+4]		,(FLAG_PRESENT|FLAG_INT_CALL)
shr eax   			,16
mov word [%2+6]		,ax

%endmacro

%macro idt_init_expt 2

lea eax   			,[exeption_%1]
mov word [%2+0] 	,ax

mov word [%2+2]		,0x0008
mov word [%2+4]		,(FLAG_PRESENT|FLAG_INT_CALL)
shr eax   			,16
mov word [%2+6]		,ax

%endmacro


Code: Select all

IDTBASE					:times 1024*4	dd 0

sidt	[orig_idt]

idt_init_expt 0x00,IDTBASE+8*0
idt_init_expt 0x01,IDTBASE+8*1

[...]

idt_init_int 0x00,IDTBASE+8*32 
idt_init_int 0x01,IDTBASE+8*33


mov word  [idtptr]       ,8*256
mov dword [idtptr+2]	 ,IDTBASE addr_to_real_mode
lidt [idtptr]	        ; charge la idt



but you probably need to also enable interupt controller, like PIC 8259 or APIC before interupt are actually enabled, maybe you need an sti to enable them as well

the interupt/exeption numbers might depend also on the interupt controller you use, in the case interupt start at 0x20 (32) because the PIC 8259 interupt master start at this number, so interupt 0 use the entry 0x20 in the idt, and exeption are mapped starting at the first entries of the idt
Elja98
Posts: 15
Joined: Fri Aug 16, 2013 1:38 pm

Re: IDT in assembly

Post by Elja98 »

I already remapped the PIC controller that shouldn't be the problem or am I missing something?
h0bby1
Member
Member
Posts: 240
Joined: Wed Aug 21, 2013 7:08 am

Re: IDT in assembly

Post by h0bby1 »

Elja98 wrote:I already remapped the PIC controller that shouldn't be the problem or am I missing something?
are you sure the pic is initialized correctly ?
Elja98
Posts: 15
Joined: Fri Aug 16, 2013 1:38 pm

Re: IDT in assembly

Post by Elja98 »

This is my code for remapping the PIC:

Code: Select all

remapPIC:
	pusha
	
	mov	al, 0x20	;EOI (reset)
	out	0x20, al	;MASTER PIC
	
	mov	al, 0x11
	out	0x20, al	;MASTER
	out	0xA0, al	;SLAVE
	
	mov	al, 0x20
	out	0x21, al	;MASTERDATA
	
	mov	al, 0x28
	out	0xA1, al
	
	mov	al, 0x04
	out	0x21, al
	
	mov	al, 0x02
	out	0xA1, al
	
	mov	al, 0x01
	out	0x21, al
	out	0xA1, al
	
	popa
	ret
egos
Member
Member
Posts: 612
Joined: Fri Nov 16, 2007 1:59 pm

Re: IDT in assembly

Post by egos »

Try this:

Code: Select all

        mov al,00010001b
        out 20h,al
        out 0A0h,al

        mov al,IRQBASE
        out 21h,al
        mov al,IRQBASE+8
        out 0A1h,al

        mov al,00000100b
        out 21h,al
        mov al,02h
        out 0A1h,al

        mov al,00001101b
        out 21h,al
        mov al,00001001b
        out 0A1h,al

        mov al,IRQMASK and 0FFh
        out 21h,al
        mov al,IRQMASK shr 8
        out 0A1h,al
If you have seen bad English in my words, tell me what's wrong, please.
h0bby1
Member
Member
Posts: 240
Joined: Wed Aug 21, 2013 7:08 am

Re: IDT in assembly

Post by h0bby1 »

http://h0bby1.eu5.org/codeigniter/index ... S/kern_pic i wrote that page about the l 8259A PIC from the spec
Elja98
Posts: 15
Joined: Fri Aug 16, 2013 1:38 pm

Re: IDT in assembly

Post by Elja98 »

I could be wrong (Please correct me if I am) but I thought you didn't need to reprogram the PIC to use software interrupts. So for software interrupts you don't have to enable interrupts (sti).
User avatar
Nessphoro
Member
Member
Posts: 308
Joined: Sat Apr 30, 2011 12:50 am

Re: IDT in assembly

Post by Nessphoro »

Yes, that's correct. You don't need to enable interrupts for software interrupts
jnc100
Member
Member
Posts: 775
Joined: Mon Apr 09, 2007 12:10 pm
Location: London, UK
Contact:

Re: IDT in assembly

Post by jnc100 »

As far as I can see, your 'Initialize_IDT' function does what is expected. I haven't looked at the PIC remap code because as pointed out earlier this shouldn't impact on software interrupts, and ideally you should check with software interrupts and generating faults (e.g. GPF and divide by zero) before moving onto external interrupts (i.e. don't call 'sti' until you've checked this works).

Things I'd check are:
1) Initialize_IDT is actually called somewhere (before the int 0x15)
2) The IDT is as you expect (use the bochs debugger 'info idt' instruction to check this)
3) gs points to a flat segment

Regards,
John.
h0bby1
Member
Member
Posts: 240
Joined: Wed Aug 21, 2013 7:08 am

Re: IDT in assembly

Post by h0bby1 »

also if you are in real mode, interupt vector are not stored in the idt but starting at physical address 0x00
Elja98
Posts: 15
Joined: Fri Aug 16, 2013 1:38 pm

Re: IDT in assembly

Post by Elja98 »

I think I've found the problem. The problem is that the "times" directive can't handle a big number like 2048. So I'm rewriting the code without having a "IDT buffer" and it should work.
User avatar
Minoto
Member
Member
Posts: 89
Joined: Thu May 12, 2011 7:24 pm

Re: IDT in assembly

Post by Minoto »

Elja98 wrote:I think I've found the problem. The problem is that the "times" directive can't handle a big number like 2048. So I'm rewriting the code without having a "IDT buffer" and it should work.
Assuming that you're using the current version of nasm (no, I'm not going to read through its change history to see if this has ever been a bug at some time in the past), the times directive can certainly handle numbers much larger than that. E.g.,

Code: Select all

times (2879 * 512) - ($ - $$) db 0
as a simple way to fill out a floppy image appended to a boot sector works just fine.
Those who understand Unix are doomed to copy it, poorly.
Elja98
Posts: 15
Joined: Fri Aug 16, 2013 1:38 pm

Re: IDT in assembly

Post by Elja98 »

So I created some new code and it works now, but still has some limitations.
I cannot make my IDT buffer 256 descriptors long. The code just doesn't work when I do 'times 256 dd 0' but when I use 'times 100 dd 0' it works perfeclty fine. I already tried all sorts of things but I just can't find the solution to this problem.

Here's my (working) code:

Code: Select all

Initialize_IDT:
	pusha
	
	mov	edx, 0x80						;We want to install interrupt 10h (INT_NUMBER * SIZE_OF_DESC) = (10h * 8h)
	call	Install_IR					;Install interrupt
	
	cli
	lidt	[idtr]						;Install the IDT
	popa
	ret

;EDX = INT_NUMBER * 8
Install_IR:
	mov	eax, IDT_start
	lea	ebx, [eax+edx]					;Get the address of our descriptor to write to

	mov	eax, handler
	
	mov	WORD [ebx], ax					;LoBase
	mov	WORD [ebx+2], 0x8				;Selector
	mov	BYTE [ebx+4], 0					;Reserved	
	mov	BYTE [ebx+5], 10001110b			;Flags
	shr	eax, 16
	mov	WORD [ebx+6], ax				;HiBase
	ret

handler:
	mov	ax, 10h
	mov	gs, ax
	mov	DWORD [gs:0xB8000], ') : '		;Print a sad smiley
	cli
	hlt
	
idtr:
	dw	IDT_end - IDT_start - 1
	dd	IDT_start

IDT_start:
times	100	dd	0				;IDT buffer
IDT_end:
In my main function I just call Initialize_IDT and call interrupt 10h.

It works but just with 100 interrupts (which is actually enough for now, but I want to add more in the future). I hope anybody knows how to solve this.


Another error :( When I try to install two interrupts :

Code: Select all

mov edx, 0x80
call Install_IR
mov edx, 0x98
call Install_IR
When I do this Bochs gives me the following error:
BxError: instruction with opcode=0xff
mod was c0, nnn was 7, rm was 7
WARNING: Encountered an unknown instruction <signalling ille
>>PANIC<< prefetch: RIP > CS.limit
Again for this error, I have no idea what the problem is. I hope one of you has.

Thanks in advance!
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 in assembly

Post by Combuster »

I cannot make my IDT buffer 256 descriptors long.
So much for a lack of sense for detail. An 256-entry IDT is at least 2048 bytes long (256 quadwords in 32-bit mode, not doublewords)

But I expect that there be many, many more errors, a lack of debugging skills, considering that
The problem is that the "times" directive can't handle a big number like 2048.
is already an user error.
"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