protected mode idt (from dos) reboot problem

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
Ben_3D

protected mode idt (from dos) reboot problem

Post 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
Dex4u

Re:protected mode idt (from dos) reboot problem

Post 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).
smiddy

Re:protected mode idt (from dos) reboot problem

Post 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.
Ben_3D

Re:protected mode idt (from dos) reboot problem

Post 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
AR

Re:protected mode idt (from dos) reboot problem

Post 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.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re:protected mode idt (from dos) reboot problem

Post 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
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.
smiddy

Re:protected mode idt (from dos) reboot problem

Post 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!
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re:protected mode idt (from dos) reboot problem

Post 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
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.
Ben_3D

Re:protected mode idt (from dos) reboot problem

Post 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
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re:protected mode idt (from dos) reboot problem

Post 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
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.
Ben_3D

Re:protected mode idt (from dos) reboot problem

Post 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

:)
smiddy

Re:protected mode idt (from dos) reboot problem

Post 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! :-[
Post Reply