Switch to PMode 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
srg

Switch to PMode Problem

Post by srg »

Hi

I'm having trouble with my code that switches to PMode and I'm not sure what I'm doing wrong.

Here is the code:

; Segment Descriptor Defenitions
; 0x00cf9a000000ffff Supervisor code from 0x00000000 to 4GB
; 0x00cf92000000ffff Supervisor data from 0x00000000 to 4GB
; 0x00cffa000000ffff User code from 0x00000000 to 4GB
; 0x00cff2000000ffff User data from 0x00000000 to 4GB

_switch_to_pmode:

cli
; Clearing the first 128KB of RAM with 00s
    ; ready for the GDT and IDT to be placed into it
    ; Not the best method, but should work ok
    mov cx, 0xFFFF ; Want to clear room for 2KB RAM
.Lower_64K
    mov ax, 0
    mov es, ax ; Want to clear segement 0
    ; NOTE!! Interrupts MUST be disabled or
                ; a crash is certain!!
    mov ax, 0
    mov bx, cx
    mov [es:bx], al
    loop .Lower_64K

    mov cx, 0xFFFF ; Want to clear room for 2KB RAM
.Upper_64K
    mov ax, 0
    mov es, ax ; Want to clear segement 0
    ; NOTE!! Interrupts MUST be disabled or
                ; a crash is certain!!
    mov ax, 1
    mov bx, cx
    mov [es:bx], al
;    loop .Upper_64K
   
   

;.setup_idt
;lidt [idtr_details]
   

.setup_gdt
    xor ax, ax
    mov es, ax

    ;------------------------------------
    ; First Setup the Segment Descriptors
    ;------------------------------------

    ; First 0x00 - The Null Selector
mov dword [es:GDT_LOCATION] , 0x00000000
    mov dword [es:GDT_LOCATION+4], 0x00000000
   
    ; Now 0x08 - the Supervisor mode code segment
    mov dword [es:GDT_LOCATION+8] , 0x0000ffff
    mov dword [es:GDT_LOCATION+12], 0x00cf9a00

    ; Now 0x10 - the Supervisor mode data segment
    mov dword [es:GDT_LOCATION+16], 0x0000ffff
    mov dword [es:GDT_LOCATION+20], 0x00cf9200
   
    ; Now 0x18 - the User mode code segment
    mov dword [es:GDT_LOCATION+24], 0x0000ffff
    mov dword [es:GDT_LOCATION+28], 0x00cffa00

    ; Now 0x20 - the User mode data segment
    mov dword [es:GDT_LOCATION+32], 0x0000ffff
    mov dword [es:GDT_LOCATION+36], 0x00cff200

    ; Finally load the GDT into the GDTR
    lgdt [gdtr_details]
   
   

       ;--------------------------------
       ; Now To switch to Protected Mode
       ;--------------------------------

       mov eax, cr0 ; Read in CR0 Register
       or eax, 1      ; Toggle PE Bit
       mov cr0, eax      ; Save to CR0

[Bits 32]

       ; That's it, we're in Protected Mode!
       ; Next, Flush the Prefetch Que
       Jmp short .flush
      
.flush

       ;-------------------------------
       ; Now to setup Segment Selectors
;-------------------------------
mov ax, 0x10
       mov ds, ax ; Setup data selectors with 0x10 + TI=0b + RPL=00b
mov es, ax
       mov fs, ax
mov gs, ax
       mov ss, ax

      
; To change cs, jump to new location
       mov ax, 0x08
       push ax
       push word .ToHere
       retf


      
.ToHere mov byte [ds:0xb8000], 'A'
      
       Jmp $
       ;pop eax
    ;retn

; Data #######################################################################

; As this is a tiny mode program, all data is still in the code segment

gdtr_details dw 0xFFFF
dd 0x0800


This program is supposed to first clear the first 128KB RAM with 0s ready for my tables to go in. Then I put in the idt (will be done at a later date) and the GDT. After that it is switched into pmode and the selectors are set up. Finally, there is a line that prints the char A to the top left had of the screen to test that it has all worked.

My problem is that I can't get this to work and I don't know that the problem is with it.

Thanks for your help
srg
Curufir

Re:Switch to PMode Problem

Post by Curufir »

Ok, I don't know how many times people have said it on this board but it's plenty. It is NOT a good idea to trash the IVT and BIOS data area by putting code below 0x600 linear. You lose all that free information from the BIOS, and the real mode vesa interrupts are lost forever. End of rant.

Took a quick peek at your code (Dunno why people are so afraid of making their descriptors legible with defines, but that's personal choice I guess :)). First glance brought up this problem.

The PMode switch must be a far jump. Reason being is a short jump will not load CS with the selector, a short jump only loads IP with an offset into the code segment.

**

My bad, I see the retf you're using to set CS. I don't like it though, you're loading DS with a selector and pushing onto the stack without loading CS with one. Maybe there isn't anything wrong with that, but it feels...yuck. Use a far jump to set CS at the same time you flush the prefetch queue.

The other thing is this clearing memory business. Why bother? Seeing as you're overwriting it then so long as you set up start and limit correctly on the GDT/IDT it doesn't matter what was there originally.

Is that GDT location constant defined as 0x800? Seeing as you've hardcoded the gdt base then it had better be.
srg

Re:Switch to PMode Problem

Post by srg »

OK slap on the had taken, I shall make it more self explanitery. :)

Anyway, without the clearing memory stuff, I get tripple faults!

I'll change the Jump which'll kill two birds with one stone, and make my program smaller.

When in pmode, is the line

mov byte [ds:0xb8000], 'A'

ok for printing the text onto screen.

thanks
srg

P.S. How do I get the FritzOS PM code?
jrfritz

Re:Switch to PMode Problem

Post by jrfritz »

Ok...<No Advertising>

Here:

http://fritzos.sourceforge.net/
Curufir

Re:Switch to PMode Problem

Post by Curufir »

srg wrote: When in pmode, is the line

mov byte [ds:0xb8000], 'A'

ok for printing the text onto screen.
Yes, but remember that there are 2 bytes, 1 for the character, one for the display properties of the character so be sure to make certain the character isn't displaying as black background with black text on a black screen (Another one of my own personal favourite mistakes :)).
srg

Re:Switch to PMode Problem

Post by srg »

right, I have revised my code but I'm still having problems, more seriouse this time.

_switch_to_pmode:
;Test Point A
?????? push ds
?????? mov ax, 0xb800
?????? mov ds, ax
?????? mov byte [ds:0], 'A'
?????? pop ds
??????
.setup_idt
lidt [IDT_location]
???

.setup_gdt
??? lgdt [GDT_location]
??????
?????? ???
?????? ;--------------------------------
?????? ; Now To switch to Protected Mode
?????? ;--------------------------------

?????? mov eax, cr0 ; Read in CR0 Register
?????? or eax, 1??????; Toggle PE Bit
?????? mov cr0, eax??????; Save to CR0



?????? ; That's it, we're in Protected Mode!
?????? ; Next, Flush the Prefetch Que
?????? Jmp Supervisor_code_selector:.ToHere
??????
[Bits 32]
.ToHere
;-------------------------------
?????? ; Now to setup Segment Selectors
;-------------------------------
mov ax, Supervisor_data_selector
?????? mov ds, ax ; Setup data selectors with 0x10 + TI=0b + RPL=00b
mov es, ax
?????? mov fs, ax
mov gs, ax
?????? mov ss, ax
mov esp, 0xFFFF
??????

?????? ;Test Point B
mov byte [ds:0xb8000], 'B'
??????
?????? retn

; Data #######################################################################

; As this is a tiny mode program, all data is still in the code segment

IDT_location dw IDT_end - IDT - 1
dd IDT

GDT_location dw GDT_end - GDT - 1
dd GDT

; Interrupt Gates
; NULL Till IDT Limit

IDT:
resq 256
IDT_end:

; Segment Descriptor Defenitions
; Null
; 0x00cf9a000000ffff Supervisor code from 0x00000000 to 4GB
; 0x00cf92000000ffff Supervisor data from 0x00000000 to 4GB
; 0x00cffa000000ffff User code from 0x00000000 to 4GB
; 0x00cff2000000ffff User data from 0x00000000 to 4GB
; Unused till GDT Limit

GDT: ; our descriptors
???; NULL descriptor
???dw 0 ; limit 15:0
???dw 0 ; base 15:0
???db 0 ; base 23:16
???db 0 ; type 15:8
???db 0 ; limit 19:16, flags
???db 0 ; base 31:24

???; Supervisor code from 0x00000000 to 4GB
???Supervisor_code_selector???EQU $-GDT
???dw 0xFFFF?????????
???dw 0????????????
???db 0????????????
???db 0x9a????????????
???db 0xCF????????????
???db 0????????????
???
???; Supervisor data from 0x00000000 to 4GB
???Supervisor_data_selector???EQU $-GDT
???dw 0xFFFF?????????
???dw 0????????????
???db 0????????????
???db 0x92????????????
???db 0xCF????????????
???db 0????????????

???; User code from 0x00000000 to 4GB
???User_code_selector???EQU $-GDT
???dw 0xFFFF?????????
???dw 0????????????
???db 0????????????
???db 0xfa????????????
???db 0xCF????????????
???db 0????????????
???
???; User data from 0x00000000 to 4GB
???User_data_selector???EQU $-GDT
???dw 0xFFFF?????????
???dw 0????????????
???db 0????????????
???db 0xf2????????????
???db 0xCF????????????
???db 0????????????

resq 251

GDT_end:



The problem is that at the line:

Jmp Supervisor_code_selector:.ToHere

I get a tripple fault witch shuts down or resets the machine (I know that a tripple fault makes the 386 reset).

What is the problem?
Slasher

Re:Switch to PMode Problem

Post by Slasher »

hi,
first disable interrupts while the code is setting up Pmode.
You did no put the selector in AX before using AX to setup you SS,DS,ES,FS and GS registers.
; Now to setup Segment Selectors
;-------------------------------
;mov ax, Supervisor_data_selector
mov ds, ax ; Setup data selectors with 0x10 + TI=0b + RPL=00b
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
mov esp, 0xFFFF


;Test Point B
mov byte [ds:0xb8000], 'B'

retn
uncomment mov ax, Supervisor_data_selector

also you are returning at the end of the code, WHY!!!
remove retn
replace with jmp $ (this is a loop to the current address)
srg

Re:Switch to PMode Problem

Post by srg »

Right, I've modified my last post and uncommented that line.

I wasn't sure if this was relavent to this but this program is part of a larger program wrtten in C using Turbo C++ 1.01, but with my own custom startup code, hence the retn.

Also this program needs to be able to be run EITHER from a bootsector/bootloader OR from the DOS prompt.

Thanks
srg
Slasher

Re:Switch to PMode Problem

Post by Slasher »

boot sectors/codes do not return! At thee end of the boot code function should be a call to the kernel/code to continue in pmode!!
call _kernel
srg

Re:Switch to PMode Problem

Post by srg »

:)

No no no this is a function in the C program hehe

Also Interrupts were disabled earlier on in the program.
and the A20 gate was opened.
Post Reply