Page 1 of 1

Bochs reboots when enter to PM

Posted: Wed Oct 04, 2006 3:53 pm
by muisei
I'm wonderin why this simple code reboots when I set the CR0 register.

Code: Select all

[BITS 16]
[ORG 0x00]

        jmp start
start:

        cli
        mov     ax,cs
        mov     ds,ax
        mov     es,ax
        mov     gs,ax
        mov     fs,ax
        mov     ss,ax
        mov     sp,0xffff
        sti

        lgdt     [gdtr]               ; Load GDT
        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

        mov     ax,datasel
        mov     ds,ax           ; Initialise ds & es to data segment
        mov     es,ax
        mov     ss,ax
        mov     fs,ax
        mov     ax,videosel     ; Initialise gs to video memory
        mov     gs,ax
        jmp     codesel:go_pm

bits 32
go_pm:
        mov BYTE [gs:0x00],'P'
        mov BYTE [gs:0x01],0x3f
jmp $
;-------------------------------------------------------------------------------------------;
;  GDT                                                                                   ;
;-------------------------------------------------------------------------------------------;
gdtr:
   dw gdt_end-gdt-1     ; Length of the gdt
   dd gdt                      ; physical address of gdt

gdt:

nullsel equ $-gdt         ; $->current location,so nullsel = 0h
gdt0:                           ; Null descriptor,as per convention gdt0 is 0
   dd 0                         ; Each gdt entry is 8 bytes, so at 08h it is CS
   dd 0
                                   ; In all the segment descriptor is 64 bits
codesel equ $-gdt       ; This is 8h,ie 2nd descriptor in gdt.Code descriptor 4Gb flat segment at 0000:0000h
   dw 0xffff            ; Limit 4Gb  bits 0-15 of segment descriptor
   dw 0x0000            ; Base 0h bits 16-31 of segment descriptor (sd)
   db 0x00              ; Base addr of seg 16-23 of 32bit addr,32-39 of sd
   db 0x09a             ; P,DPL(2),S,TYPE(3),A->Present bit 1,Descriptor
                        ; privilege level 0-3,Segment descriptor 1 ie code
                        ; or data seg descriptor,Type of seg,Accessed bit
   db 0x0cf             ; Upper 4 bits G,D,0,AVL ->1 segment len is page
                        ; granular, 1 default operation size is 32bit seg
                        ; AVL : Available field for user or OS
                        ; Lower nibble bits 16-19 of segment limit
   db 0x00              ; Base addr of seg 24-31 of 32bit addr,56-63 of sd

datasel equ $-gdt       ; ie 10h, beginning of next 8 bytes for data sd.Data descriptor 4Gb flat seg at 0000:0000h
   dw 0x0ffff           ; Limit 4Gb
   dw 0x0000            ; Base 0000:0000h
   db 0x00              ; Descriptor format same as above
   db 0x092
   db 0x0cf
   db 0x00

videosel equ $-gdt      ; ie 18h,next gdt entry
   dw 3999              ; Limit 80*25*2-1
   dw 0x8000            ; Base 0xb8000
   db 0x0b
   db 0x92              ; present,ring 0,data,expand-up,writable
   db 0x00              ; byte granularity 16 bit
   db 0x00
gdt_end
10x in advance

Posted: Wed Oct 04, 2006 6:42 pm
by Dex
You need to disable interrupts on entering pmode (eg: cli ,)as you have not set idt up yet, also set these:

Code: Select all

      mov     ax,datasel 
        mov     ds,ax           ; Initialise ds & es to data segment 
        mov     es,ax 
        mov     ss,ax 
        mov     fs,ax 
        mov     ax,videosel     ; Initialise gs to video memory 
        mov     gs,ax 
After the jump to pmode.

Posted: Thu Oct 05, 2006 3:03 am
by muisei
I rewrote the code like this but still no success.
Bochs says: "exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting"
It continues to reboot at "mov cr0,eax"

Code: Select all

[BITS 16] 
[ORG 0x00] 

        jmp start 
start: 

        cli 
        mov     ax,cs 
        mov     ds,ax 
        mov     es,ax 
        mov     gs,ax 
        mov     fs,ax 
        mov     ss,ax 
        mov     sp,0xffff 
        
        xor eax,eax                    <- Added
        mov ax,ds                      <- Added
        shl eax,4                        <- Added
        add eax,gdt                   <- Added
        mov [gdtr+2],eax           <- Added

        lgdt     [gdtr]             ; Load GDT 
        mov     eax,cr0         ; The lsb of cr0 is the protected mode bit 
        or        al,0x01         ; Set protected mode bit
        mov     cr0,eax

        jmp     codesel:go_pm 

bits 32 
go_pm: 
        sti                          <- Added here
        mov     ax,datasel 
        mov     ds,ax           ; Initialise ds & es to data segment 
        mov     es,ax 
        mov     ss,ax 
        mov     fs,ax 
        mov     ax,videosel     ; Initialise gs to video memory 
        mov     gs,ax 


        mov BYTE [gs:0x00],'P' 
        mov BYTE [gs:0x01],0x3f 
jmp $

Posted: Thu Oct 05, 2006 9:03 am
by Dex
What if you add "org 0x7C00" to the start ?.
As this code works fine for me

Code: Select all

org 0x7C00

use16
;****************************
; Realmode startup code.
;****************************

start:
        xor   ax,ax
        mov   ds,ax
        mov   es,ax
        mov   ss,ax
        mov   sp,0x7C00


;*****************************
; Setting up, to enter pmode.
;*****************************

        cli
        lgdt  [gdtr]

        mov   eax, cr0
        or    al,0x1
        mov   cr0,eax

        jmp   0x10: protected

;*****************************
; Pmode. ;-)
;*****************************

use32
protected:
        mov   ax,0x8
        mov   ds,ax
        mov   es,ax
        mov   ss,ax
        mov   esp,0x7C00
;*****************************
; Turn floppy off (if space).
;*****************************

        mov   dx,3F2h
        mov   al,0
        out   dx,al

        mov   byte [es:0xB8000], "P"
        jmp   $
;*************************************
; GDT.
;*************************************

gdt:        dw    0x0000, 0x0000, 0x0000, 0x0000
sys_data:   dw    0xFFFF, 0x0000, 0x9200, 0x00CF
sys_code:   dw    0xFFFF, 0x0000, 0x9800, 0x00CF
gdt_end:

gdtr:	    dw gdt_end - gdt - 1	                                  
	    dd gdt
;*************************************
; Make program 510 byte's + 0xaa55
;*************************************

times 510- ($-start)  db 0  
dw 0xaa55
NOTE: assembled with fasm.

Posted: Thu Oct 05, 2006 10:22 am
by muisei
The code is loaded by the MBR at address 0x50:0x00.Coud that be the problem?

Posted: Thu Oct 05, 2006 10:29 am
by Dex
Yes as the address will be wrong, here are the seting for a com file loaded to that address "COM program defaults: cs = ds = es = ss = 50h, sp = 0, ip = 100h"

Posted: Thu Oct 05, 2006 1:01 pm
by muisei
But the free convencional memory resides from 0x500 to 0x9FBFF, isn't it.

Posted: Fri Oct 06, 2006 9:54 am
by Dex
But 50h is not real 50h, but 500h, somthing like this
;; ;;
;; Memory Map: ;;
;; ~~~~~~~~~~~ ;;
;; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ;;
;; ³ Interrupt Vector Table ³ 0000 ;;
;; ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ;;
;; ³ BIOS Data Area ³ 0040 ;;
;; ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ;;
;; ³ PrtScr Status / Unused ³ 0050 ;;
;; ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ;;
;; ³ Image Load Address ³ 0060 ;;
;; ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ;;
;; ³ Available Memory ³ nnnn ;;
;; ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ;;
;; ³ 2KB Boot Stack ³ A000 - 512 - 2KB ;;
;; ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ;;
;; ³ Boot Sector ³ A000 - 512 ;;
;; ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ;;
;; A000 ;;
;; ;;
;; ;;
;; Boot Image Startup (register values): ;;
;; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ;;
;; dl = boot drive number ;;
;; cs:ip = program entry point ;;
;; ss:sp = program stack (don't confuse with boot sector's stack) ;;
;; COM program defaults: cs = ds = es = ss = 50h, sp = 0, ip = 100h ;;
;; EXE program defaults: ds = es = 50h, other stuff depends on EXE header ;;

Posted: Fri Oct 06, 2006 1:47 pm
by muisei
Also found this document which may be useful.
http://www.frontiernet.net/~fys/rombios.htm

Acording to what you said and this document, it seems perfectly legal to me to load my kernel at linear address from 0x600 to 0x9fbff whitout worring that I can overlap some useful code.Is that true?

Posted: Fri Oct 06, 2006 5:14 pm
by Dex
Yes

Posted: Sat Oct 07, 2006 1:49 am
by muisei
thanks for the enlightening. :)