Problems with Interrupts and call gates
Problems with Interrupts and call gates
Hello,
the file I attached to the message (os.zip) is a simplified version of my OS. It contains five files:
[*] 1.44 (the image file) which is a binary file that you can run under Bochs or write to the first sectors of the first floppy drive,
[*] Make.bat which is the batch file I use to compile the source, [*]boot.txt which is (as you probably guessed) the boot loader,
[*]init.txt which is the second stage and kernel.txt the kernel.
In the second stage, I setup the GDT and the IDT, do the PM stuff, then load the kernel.
When the kernel is loaded, it crashes. I'm trying to use a call gate and an interrupt but both are not working. Maybe I misunderstood or forgot something concerning PM.
Thanks for any help.
the file I attached to the message (os.zip) is a simplified version of my OS. It contains five files:
[*] 1.44 (the image file) which is a binary file that you can run under Bochs or write to the first sectors of the first floppy drive,
[*] Make.bat which is the batch file I use to compile the source, [*]boot.txt which is (as you probably guessed) the boot loader,
[*]init.txt which is the second stage and kernel.txt the kernel.
In the second stage, I setup the GDT and the IDT, do the PM stuff, then load the kernel.
When the kernel is loaded, it crashes. I'm trying to use a call gate and an interrupt but both are not working. Maybe I misunderstood or forgot something concerning PM.
Thanks for any help.
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:Problems with Interrupts and call gates
ever considered naming your sources files ".asm" instead of ".txt" ?
Your GDT setting seems correct ...
I'm more concerned by taht 'int13h' code, which will fail to catch any errors ...
having so much instructions after 'mov cr0,eax' and before setting up a valid CS selector also concerns me.
i'd have had
if i were you ...
you also know all these 'calculations' of addresses may be performed at compile time since the load address (0x1000) for init.txt is well-known.
Your GDT setting seems correct ...
Code: Select all
[gdtdescr].limit := GDTend - GDT
[gdtdescr].base := ds*16 + GDT
Code: Select all
mov ax,900h
mov es,ax
xor bx,bx
mov ah,2
mov al,3
xor ch,ch
mov cl,4
xor dx,dx
int 13h
i'd have had
Code: Select all
mov cr0, eax
jmp 0x08:.here
.here:
mov eax, 0x10
mov ds, eax
...
you also know all these 'calculations' of addresses may be performed at compile time since the load address (0x1000) for init.txt is well-known.
Re:Problems with Interrupts and call gates
Hi,
The offset for all of your IDT entries is also wrong. You use a 16 bit offset for them but you are also using a 32 bit code segment (which will need a 32 bit offset). In addition you are trying to use the 32 bit code segment to run 16 bit code.
As a side note, things like:
db 0eah
dw 9000h
dw 8h
Are normally written as:
jmp 8h:9000h
NASM is actually quite useful like that - you can even get it to generate a 32 bit far jump in a 16 bit segment:
jmp dword 8h:12345678h
Cheers,
Brendan
The offset in your call gate's GDT entry is 0x0000000, which is why your call gate crashes. You need to set it to an address in some 32 bit code.ManOfSteel wrote: When the kernel is loaded, it crashes. I'm trying to use a call gate and an interrupt but both are not working. Maybe I misunderstood or forgot something concerning PM.
The offset for all of your IDT entries is also wrong. You use a 16 bit offset for them but you are also using a 32 bit code segment (which will need a 32 bit offset). In addition you are trying to use the 32 bit code segment to run 16 bit code.
As a side note, things like:
db 0eah
dw 9000h
dw 8h
Are normally written as:
jmp 8h:9000h
NASM is actually quite useful like that - you can even get it to generate a 32 bit far jump in a 16 bit segment:
jmp dword 8h:12345678h
Cheers,
Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
Re:Problems with Interrupts and call gates
Hello,
Pype.Clicker,
Brendan,
Isn't that supposed to "divide" the 32bits offset address of the call gate into two 16bits offset adresses? (call gates need two 16bits addresses)
Thanks for your help.
Pype.Clicker,
Since I program under Window$ and open my source code directly with notepad, I didn't bother creating a new file type entry for *.asm files.ever considered naming your sources files ".asm" instead of ".txt" ?
I will keep these as they are for now, after all everything is working even at the kernel level when I try to print a letter directly to VGA memory.I'm more concerned by taht 'int13h' code, which will fail to catch any errors ...
I've already tried that before but it was causing triple faults, that's why I made it three stages and now it's working fine with a jump to "8h:9000h" at the end of init.txt.having so much instructions after 'mov cr0,eax' and before setting up a valid CS selector also concerns me.
i'd have hadif i were you ...Code: Select all
mov cr0, eax jmp 0x08:.here .here: mov eax, 0x10 mov ds, eax ...
How is that done?you also know all these 'calculations' of addresses may be performed at compile time since the load address (0x1000) for init.txt is well-known.
Brendan,
That's why I use the following code before loading the GDT (with lgdt)The offset in your call gate's GDT entry is 0x0000000, which is why your call gate crashes. You need to set it to an address in some 32 bit code.
Code: Select all
mov ebx,cg1 ;calculate call gate offset
mov [CallGate01],bx
shr ebx,16
mov [CallGate01+6],bx
TASM programming after-effects.As a side note, things like:
db 0eah
dw 9000h
dw 8h
Are normally written as:
jmp 8h:9000h
Can you please show me an excerpt of your IDT, I will understand it better.The offset for all of your IDT entries is also wrong. You use a 16 bit offset for them but you are also using a 32 bit code segment (which will need a 32 bit offset). In addition you are trying to use the 32 bit code segment to run 16 bit code.
Thanks for your help.
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:Problems with Interrupts and call gates
the problem was probably due to the fact than, since .here, you need to tell the assembler to produce *32 bits* code rather than *16 bits*, still if it works with late-jumping. Fine. Clean. easy to understand ...ManOfSteel wrote: Hello,
I've already tried that before but it was causing triple faults, that's why I made it three stages and now it's working fine with a jump to "8h:9000h" at the end of init.txt.having so much instructions after 'mov cr0,eax' and before setting up a valid CS selector also concerns me.
i'd have hadif i were you ...Code: Select all
mov cr0, eax jmp 0x08:.here .here: mov eax, 0x10 mov ds, eax ...
Let's say, for instance you have your init.txt loaded at 0x1000:0x0000. and assembled with [ORG 0] (that is, the code file is loaded at the start of a 16-bits segment).How is that done?you also know all these 'calculations' of addresses may be performed at compile time since the load address (0x1000) for init.txt is well-known.
Now let's say you have symbol GDT that you wish to place in GDTR.base, all you have to write is
Code: Select all
gdtr:
dw gdtend - gdt - 1
dd gdt + 0x1000 * 16
Re:Problems with Interrupts and call gates
Hi,
I assume that eventually your 32 bit kernel will contain the interrupt handling code, and that the call gate will be used for the kernel API (which would also be in the kernel binary). Rather than fixing the current problems you may want to shift this code into the kernel now...
Cheers,
Brendan
Sorry, I missed that. Your call gate has the same problem as your interrupt gates - the wrong offset and using 16 bit code with a 32 bit code segment.ManOfSteel wrote:That's why I use the following code before loading the GDT (with lgdt)The offset in your call gate's GDT entry is 0x0000000, which is why your call gate crashes. You need to set it to an address in some 32 bit code.
I assume that eventually your 32 bit kernel will contain the interrupt handling code, and that the call gate will be used for the kernel API (which would also be in the kernel binary). Rather than fixing the current problems you may want to shift this code into the kernel now...
Not really - my kernel contains 3 seperate lists of offsets to use for IDT entries. The boot code uses these lists to dynamically create the IDT. The first list is for exception handlers and is always used. The second list is for IRQs and is only used if the PIC chips are used. The third list is also for IRQs but is only used if IO APIC/s are used instead of the PIC chips. My boot code detects if IO APIC/s will be used or not and builds the IDT accordingly.ManOfSteel wrote: Can you please show me an excerpt of your IDT, I will understand it better.
Cheers,
Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
Re:Problems with Interrupts and call gates
Hello,
sorry I couldn't reply before because I had no more Internet.
Anyway, ...
I tried to make a one staged "OS" and everything went OK (the call gate, the interrupt, ...).
But now I'm trying to make it (the one staged "OS") a two staged OS and it won't work. It is causing triple faults even before I use the call gate or interrupt (actually when I'm setting up PM). It is printing 'test' to the screen than when I press any key it crashes BOCHS.
Please help me find the error.
Thanks.
sorry I couldn't reply before because I had no more Internet.
Anyway, ...
Ok, so you're saying I have to move my GDT, my IDT and maybe all my PM stuff to the kernel making my OS two staged instead of three staged. If that's the case, than I already tried that but it was causing me a lot of trouble and that's why I decided to make it three staged.Rather than fixing the current problems you may want to shift this code into the kernel now...
I tried to make a one staged "OS" and everything went OK (the call gate, the interrupt, ...).
But now I'm trying to make it (the one staged "OS") a two staged OS and it won't work. It is causing triple faults even before I use the call gate or interrupt (actually when I'm setting up PM). It is printing 'test' to the screen than when I press any key it crashes BOCHS.
Please help me find the error.
Thanks.
Re:Problems with Interrupts and call gates
Hi,
..and..
Because this code is assembled with ORG = 0x0 and is actually running at 0x90000, every offset that you use in protected mode will be wrong and you'll need to add 0x90000 to them to fix it.
I'd recommend making the first stage contain 16 bit code only, and the second stage contain 32 bit code only. Then you could use the correct ORG for each. For e.g.:
"BOOT.TXT"
..and..
"KERNEL.TXT"
Cheers,
Brendan
The problems with your 2 stage code are all the same mistake - you forget that the code is running at 0x90000 (or 0x9000:0x0000 in real mode). Change these bits:ManOfSteel wrote: I tried to make a one staged "OS" and everything went OK (the call gate, the interrupt, ...).
But now I'm trying to make it (the one staged "OS") a two staged OS and it won't work. It is causing triple faults even before I use the call gate or interrupt (actually when I'm setting up PM). It is printing 'test' to the screen than when I press any key it crashes BOCHS.
Code: Select all
mov ebx,cg1+0x90000
mov [callgate1],bx
shr ebx,16
mov [callgate1+6],bx
mov ebx,donothing+0x90000
mov [interone],bx
shr ebx,16
mov [interone+6],bx
Code: Select all
jmp dword 8h:pm+0x90000
[bits 32]
I'd recommend making the first stage contain 16 bit code only, and the second stage contain 32 bit code only. Then you could use the correct ORG for each. For e.g.:
"BOOT.TXT"
Code: Select all
bits 16
org 0x7C00
%define kernelAddress 0x90000
jmp 0x00:start
start:
..set DS, ES and SS:ESP..
..load 32 bit code into memory..
..copy GDT to fixed address..
..load the GDT..
cli
mov eax,cr0
or eax,1
mov cr0,eax
jmp dword 0x08:kernelAddress
"KERNEL.TXT"
Code: Select all
bits 32
org 0x90000
jmp start
start:
..set DS, ES and SS:ESP..
..setup IDT..
..add call gate to GDT..
jmp $
Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
Re:Problems with Interrupts and call gates
Hmm. Well as Brendan says you're going to have to patch up those memory references for the ISR/Call Gate entry points.
Couple of things I noticed looking through:
Is pretty pointless.
If you're using NASM (That's what it looks like), then I think this gets encoded with only a 16-bit offset when used in a 16-bit section, which would be wrong. I'm not totally sure though, so diassemble and check. Any way you look at it you're going to have to hardcode the base somewhere. Either as a non-zero base for the pmode code segment (Yuck!) or as a define in your assembly. Reason being that a far jump has the form immediate:immediate, so you can't patch up the address in a register and pass it that way (Brendan already pointed this out).
This is redundant (And the wrong value anyway) since you calculate it correctly using the preprocessor when defining your GDT (Same goes for the IDT code).
Something fun for the future (Once you get into PMode).
This is fine for calling your interrupt, with the minor problem that when you iret all interrupts will be enabled again. Since you haven't remapped/masked the PICs you'll start getting timer interrupts hitting on your 'donothing' routine at 18.2hz. This is not a bad thing (The output won't ever change so it's unlikely you'll even notice), and since you acknowledge the IRQ I'm guessing it's what you wanted. Problem is that you're not handling any of the other IRQs, so anything but the timer is going to triple fault the processor. Just something to keep aware of.
Couple of things I noticed looking through:
Code: Select all
jmp next
next:
Code: Select all
jmp 8h:pm
Code: Select all
mov ax,GDTEND ;calculate GDT limit
mov bx,GDT
sub ax,bx
Something fun for the future (Once you get into PMode).
Code: Select all
int 0h
Re:Problems with Interrupts and call gates
Hi,
Cheers,
Brendan
Not quite - "int 0h" is using an interrupt gate, which will push eflags, disable interrupts and then pop eflags, so that the interrupt disable flag would remain unchanged...Curufir wrote:This is fine for calling your interrupt, with the minor problem that when you iret all interrupts will be enabled again.Code: Select all
int 0h
Cheers,
Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
Re:Problems with Interrupts and call gates
Serves me right for posting before coffee ;D.