Page 1 of 2
IDT in assembly
Posted: Sun Aug 25, 2013 11:48 am
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!
Re: IDT in assembly
Posted: Sun Aug 25, 2013 12:08 pm
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
Re: IDT in assembly
Posted: Sun Aug 25, 2013 12:39 pm
by Elja98
I already remapped the PIC controller that shouldn't be the problem or am I missing something?
Re: IDT in assembly
Posted: Sun Aug 25, 2013 1:04 pm
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 ?
Re: IDT in assembly
Posted: Sun Aug 25, 2013 11:52 pm
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
Re: IDT in assembly
Posted: Mon Aug 26, 2013 10:53 am
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
Re: IDT in assembly
Posted: Mon Aug 26, 2013 11:30 am
by h0bby1
http://h0bby1.eu5.org/codeigniter/index ... S/kern_pic i wrote that page about the l 8259A PIC from the spec
Re: IDT in assembly
Posted: Mon Aug 26, 2013 12:41 pm
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).
Re: IDT in assembly
Posted: Mon Aug 26, 2013 12:56 pm
by Nessphoro
Yes, that's correct. You don't need to enable interrupts for software interrupts
Re: IDT in assembly
Posted: Mon Aug 26, 2013 2:35 pm
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.
Re: IDT in assembly
Posted: Mon Aug 26, 2013 7:57 pm
by h0bby1
also if you are in real mode, interupt vector are not stored in the idt but starting at physical address 0x00
Re: IDT in assembly
Posted: Mon Aug 26, 2013 11:22 pm
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.
Re: IDT in assembly
Posted: Tue Aug 27, 2013 12:52 am
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.
Re: IDT in assembly
Posted: Tue Aug 27, 2013 12:07 pm
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!
Re: IDT in assembly
Posted: Tue Aug 27, 2013 3:31 pm
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.