Page 1 of 1

protected mode idt (from dos) reboot problem

Posted: Wed May 18, 2005 7:45 am
by Ben_3D
Hi Everyone,
thanks again for helping me with my last problem... getting into protected mode from dos :)

I'm still working on the same project for fun... great stuff I think...but have hit a wall again...I'm dang sure its to do with offsets.

As I can setup the gdt and write info to the screen etc, thanks to Brendon, smiddy, BE etc....thanks for that guys.

But now I'm trying to set the idt using a similar method...nothing amazing...just to catch an interrupt 0...divide by 0. I've tried to disable any other interrupts, nmi's etc.....but when I trigger the int 0x0, it seems to reboot...so I can only guess that my theory is wrong or you need more interrupts for a basic...or something I dont' know about :(

The code is bit long... nothing complex...but would be great if some people could throw some ideas at me on how to fix this..
I know it might be easier doing a binary kernal and loading it into memory ...but just for simple learning of asm and the pc components etc I find this method more fun :)


Here is the main parts of the asm code for the idt


Code: Select all


;~~~~~~~~~~~~~other asm, dos stuff cut out so we dont' loose focus on the problem

jumpOffset:
    dd go_pm
    dw 0x08

; Offset address to our simple test interrupt
int_start :
   dd int_test
   dw 0x08

entry:
 
; Thanks from Brendan, as we have to make sure our GDTR points to the actual
; memory address, add code location and dos 0x100 onto our loaded offset 

    mov eax,0
    mov ax,cs
    shl eax,4
    add [gdtr+2],eax
    add [idtr+2],eax         ; set idtr and gdtr so it points to the 'real' address in memory
    add [jumpOffset],eax     ; do the same for our 32 pm addr

    add [int_start], eax     ; Set the value of int_start (our simple interrupt function) so
                             ; it has the "physical" address
    
    mov eax, [int_start]     ; Lets put this "physical" address value into our idt first address
    mov word [idt_start], ax ; word...so our idt interrupt 0 has the correct real address in 
                             ; physical memory
    

  cli          ; Clear or disable interrupts
  
  mov     al, 0x70
  mov     dx, 0x80
  out     dx, al      ; outb(0x80, 0x70) - disable NMI
          

  lgdt[gdtr]       ; Load GDT
  
  lidt[idtr]       ; Load IDT
     
  mov eax,cr0       ; The lsb of cr0 is the protected mode bit
  or al,0x01       ; Set protected mode bit
  mov cr0,eax       ; Mov modified word to the control register

jmp far dword [jumpOffset]  ;can't just use "jmp go_pm" as where in dos!

;                                 32 BIT
;---------------------------------------------------------------------------
[BITS 32]
go_pm :

mov ax, 0x10        ; use our datasel selector ( alternatively mov ax, datasel )
mov ds, ax,
mov es, ax
mov fs, ax
mov gs, ax

mov esp, 0fffffh    ; we need a simple stack if where calling functions!

mov word [es: 0xb8000],0x740 ; put a char to the screen!...yeahh!
                             ; Where all okay here :)

~ACCKKKK... REBOOTS !!!!!!!!!!!!!!!!!!!!!!!!!!
; Force a call to interrupt 0!
  Int 0x0           ; We call our interrupt 0 subroutine

; Do a divide by 0 error, so we force a call to our interrupt 0
;  mov eax, 0
;  mov ebx, 0
;  div ebx            ; eax divided by ebx, and stored back in eax


lp: jmp lp  ; loops here forever and ever...

;~~~~~~~other asm etc gdt values


align 4

; Our IDTR register value
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

idtr :
   dw idt_end - idt_start - 1  ; Length of the idt
   dd idt_start        ; physical address of idt


; This is the start of our idt - its actual value
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
align 4
idt_start:
   dw int_test         ; Address of our interrupt function
   dw 0x0008          ; selector
   db 0x00             ; control parameters
   db 0x86             ; access details
   dw 0x0              ; higher 16bits of our int address
idt_end:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; Nothing special, just a very basic interrupt function so we know something
; has happened
;-------------------------------------------------------------------------
int_test:
pushad
push es

nop  ; just ignore.. :)  no operations
nop

mov ax,0x10
mov es,ax
mov byte [es: 0xb8004], "R" ; poke a character into the graphics output screen

pop es
popad
iret

Re:protected mode idt (from dos) reboot problem

Posted: Wed May 18, 2005 10:43 am
by Dex4u
I have not the time right now to look at your code, but "Dex4u" the OS i am making with a team of other coders can boot from Dos just by running kernel32.exe from Dos you can look over it asm code here: http://falconrybells.co.uk/Dex4.zip
or down load the OS here: http://falconrybells.co.uk
or check out the forum here : http://dex.7.forumer.com/

Just run "kernel32.exe" from Dos (not a dos box).

Re:protected mode idt (from dos) reboot problem

Posted: Wed May 18, 2005 10:48 am
by smiddy
Just a quick look at your IDT. Here's a note:

Code: Select all

; interupt gate 00
   dw isr        ; (lower 16-bit offset) offset 0...15
   dw 0008h       ; code segment selector
   db 00000000b   ; reserved
   db 10001110b   ; P=1,dpl=00,0,d=1=32bit,xxx
   dw 0           ; offset 31...16
Not looking at the code, as I'm at work, but the only thing glaring at me, I think it should be 8Eh and not 86h that you have there.

Gotta run...I'll look closer when I get home.

Re:protected mode idt (from dos) reboot problem

Posted: Wed May 18, 2005 1:39 pm
by Ben_3D
Well smiddy, I changed the 86h to 8Eh as you recommended...but it still rebooted...hmmm

I also found out that it I shouldn't use an int instruction.....as I've only implemented that 1 interrupt in the IDT table...and it can cause other interrupts..

; Force a call to interrupt 0!
; Int 0x0 ; We call our interrupt 0 subroutine

; Do a divide by 0 error, so we force a call to our interrupt 0
mov eax, 0
mov ebx, 0
div ebx

Do an actual divide by zero.

I've been fiddling around with it all afternoon...and eventually decided to install bochs, just to see what I find...and this is what it says, just prior to rebooting:


00094282085i[CPU0 ] -----------------------------------
00094282085i[CPU0 ] selector->index*8 + 7 = 28535
00094282085i[CPU0 ] gdtr.limit = 23
00094282085i[CPU0 ] fetch_raw_descriptor: GDT: index > limit
00094282085i[CPU0 ] protected mode
00094282085i[CPU0 ] CS.d_b = 32 bit
00094282085i[CPU0 ] SS.d_b = 32 bit
00094282085i[CPU0 ] | EAX=00017006 EBX=000000ff ECX=00000008 EDX=00009101
00094282085i[CPU0 ] | ESP=0000abff EBP=abf30912 ESI=0100fffe EDI=63690010
00094282085i[CPU0 ] | IOPL=3 NV UP DI PL NZ NA PE NC
00094282085i[CPU0 ] | SEG selector base limit G D
00094282085i[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D
00094282085i[CPU0 ] | CS:0008( 0001| 0| 0) 00000000 000fffff 1 1
00094282085i[CPU0 ] | DS:0010( 0002| 0| 0) 00000000 000fffff 1 1
00094282085i[CPU0 ] | SS:0010( 0002| 0| 0) 00000000 000fffff 1 1
00094282085i[CPU0 ] | ES:0010( 0002| 0| 0) 00000000 000fffff 1 1
00094282085i[CPU0 ] | FS:0010( 0002| 0| 0) 00000000 000fffff 1 1
00094282085i[CPU0 ] | GS:0010( 0002| 0| 0) 00000000 000fffff 1 1
00094282085i[CPU0 ] | EIP=0000914a (00009149)
00094282085i[CPU0 ] | CR0=0x00000011 CR1=0 CR2=0x00000000
00094282085i[CPU0 ] | CR3=0x00000000 CR4=0x00000000
00094282085i[CPU0 ] -----------------------------------
00094282085e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
00094282085i[SYS ] bx_pc_system_c::Reset(SOFTWARE) called
00094282085i[APIC0] local apic in CPU apicid=00 initializing


I mean I'm not sure what a 3rd exception is...I'm assuming its gone somewhere wrong and its constantly doing wrong executions etc.

Hmmmmm

Re:protected mode idt (from dos) reboot problem

Posted: Wed May 18, 2005 6:02 pm
by AR
3rd exception means it raised 3 interrupts of which none were handled and triple fault (CPU crash reboot)
00094282085i[CPU0 ] selector->index*8 + 7 = 28535
00094282085i[CPU0 ] gdtr.limit = 23
00094282085i[CPU0 ] fetch_raw_descriptor: GDT: index > limit
This essentially says the GDT descriptor you tried to load is beyond the end of the GDT (you tried to load GDT descriptor number 3566)

I haven't got time to check what it causing it but it is most likely the IDT.

Re:protected mode idt (from dos) reboot problem

Posted: Wed May 18, 2005 11:11 pm
by Brendan
Hi,

This code:

Code: Select all

    mov eax, [int_start]    ; Lets put this "physical" address value into our idt first address
    mov word [idt_start], ax ; word...so our idt interrupt 0 has the correct real address in 
                            ; physical memory
Would need to correct the entire 32 bits, rather than just the lowest 16 bits (unless you can guarantee that the interrupt handler is in the first 64 Kb of memory, which you can't).

Try:

Code: Select all

    mov eax, [int_start]
    mov word [idt_start], ax
    shr eax,16
    mov word [idt_start+6], ax
It may not be the only problem, but...

How long are you going to continue with the messed up offsets before you give up? Wouldn't it be better to fix them now instead?


Cheers,

Brendan

Re:protected mode idt (from dos) reboot problem

Posted: Thu May 19, 2005 5:53 am
by smiddy
Brendan wrote: Hi,

This code:

Code: Select all

    mov eax, [int_start]    ; Lets put this "physical" address value into our idt first address
    mov word [idt_start], ax ; word...so our idt interrupt 0 has the correct real address in 
                            ; physical memory
Would need to correct the entire 32 bits, rather than just the lowest 16 bits (unless you can guarantee that the interrupt handler is in the first 64 Kb of memory, which you can't).
I saw this too, but since he's booting straight to this code, it shouldn't be outside the boundary. Never the less you are correct, he needs to convert to 32-bit linear address in case he adds more code between locations of code (which is going to happen if you continue OS programming).

From reading the text I expect that you need to cover the rest of the possible exceptions. Look at Dex4u's code. The IDT spells out which ISRs he uses for all the reserved exceptions. These can happen without your knowledge well before you call your divide by zero.

Unfortunately, last night I had an allergy attack and didn't get the opportunity to look at your code again...perhaps I will tomorrow, unless I see that you've figured it out. Good luck!

Re:protected mode idt (from dos) reboot problem

Posted: Thu May 19, 2005 6:16 am
by Brendan
Hi,
smiddy wrote:I saw this too, but since he's booting straight to this code, it shouldn't be outside the boundary.
No! If it was boot sector code this would be the case, but as it's a DOS executable it uses the memory area that DOS assigns, which could be anywhere (especially on computres that actually use DOS, and have device drivers loaded by config.sys and autoexec.bat).


Cheers,

Brendan

Re:protected mode idt (from dos) reboot problem

Posted: Thu May 19, 2005 3:51 pm
by Ben_3D
Hi guys,
well I tried fixing the address as Brendan said... lower and upper part of the address. As I was making the silly assumption of it all being a lower address, but as Brendan said, dos could load it anywhere.
Still reboots, but I'm sure its close.

I know its messy fixing all these offsets and things...but I'm just doing it for fun...few hours now and then after work... but once I get a good understanding I'll probably do a binary kernal version...but for now I'm happy just fiddling with dos :) Sorry to be a trouble on this, I know its messy and things...but I find it more educational :)

I'm sure that the idtr register address is set right..its set the same way as the gdtr register....and well I'm pretty sure that the interrupt address is set right...I'm thinking that you can't have just 1 interrupt in the idt table....I might have to add some more?

Not sure why...but interrupt seems to be very unstable...as if I do just nops...it seems to be okay...doesn't reboot I mean...but if I add a few mov instructions it causes it to reboot...hmmmm


int_test:
pushad
push es

nop ; just ignore.. :) no operations
nop
nop
nop
nop
nop

pop es
popad
iret


reboots on exception with this...hmmmm

int_test:
pushad
push es
nop ; just ignore.. :) no operations
nop
mov ebx, 5
mov ax,0x10
pop es
popad
iret

I'm not missing something here....like maybe my stack settup is wrong?...dont' think it could be...or if I have to init something in interrupts...or gdt values have to be different if I have an idt settup?....hmmmm


Thanks for your ideas guys...and sorry to be such a pain with this

Re:protected mode idt (from dos) reboot problem

Posted: Thu May 19, 2005 8:27 pm
by Brendan
Hi,
Ben_3D wrote:Not sure why...but interrupt seems to be very unstable...as if I do just nops...it seems to be okay...doesn't reboot I mean...but if I add a few mov instructions it causes it to reboot...hmmmm
I think you've switched the assembler back to 16 bit code before your interrupt handler (ie. with a "[BITS 16]").

Instructions like "NOP" would be the same regardless, but something like "mov ebx,5" would become "mov bx,5" which is a different length (2 bytes shorter). This would cause the CPU to treat the last 2 bytes of this instruction as the start of another instruction (probably an "add" as it'd be opcode 0).

To make sure, just add a "[BITS 32]" just before your interrupt handler...


Cheers,

Brendan

Re:protected mode idt (from dos) reboot problem

Posted: Thu May 19, 2005 9:51 pm
by Ben_3D
Hey Brendan,
your a legend! I'd never had seen that!... it seems to work okay now with the added 'bits 32' as you said.
Very silly mistake of me using bits 16 for the alignment of my gdt/idt data and then forgetting that anything after it would still be in 16bit mode :-/

Very happy now.. wouldn't have seen that error....amazing that you spotted it........going to tinker around with it some more tomorrow after work...see if I can add a few more interrupts etc.

Thanks again....absolutely made up now :)

Ben

:)

Re:protected mode idt (from dos) reboot problem

Posted: Mon May 23, 2005 5:49 am
by smiddy
Brendan wrote: Hi,
smiddy wrote:I saw this too, but since he's booting straight to this code, it shouldn't be outside the boundary.
No! If it was boot sector code this would be the case, but as it's a DOS executable it uses the memory area that DOS assigns, which could be anywhere (especially on computres that actually use DOS, and have device drivers loaded by config.sys and autoexec.bat).
Sorry, my bad. I didn't see that part where it was being loaded from DOS. It was a rough week last week... :'( I made the assumption this was booted code...ARGH! :-[