protected mode idt (from dos) reboot problem
Posted: Wed May 18, 2005 7:45 am
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
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