switching 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
osnewbie

switching to pmode problem...

Post by osnewbie »

hi, this is my code, for some reason it will display the "I" in real mode, pause, but then reboot without displaying the "H" i dont know why anyone know what may be up with it or what i forgot? this is my first time trying to switch to pmode... (oh by the way i use NASM)

jmp begin

bits 16

gdtr:
dw gdt_end-gdt-1
dd gdt

gdt:
gdt0: ;Null Descriptor (0)
dd 0
dd 0
gdtCode: ;Code Descriptor (1) 4GB
dw 0ffffh
dw 0
db 0
db 10011010b ;present, dpl 0, non-system, type code/execute/read (0Ah)
db 11001111b ;g=1, d/b=1
db 0

gdtData: ;Data Descriptor (2) 4GB
dw 0ffffh
dw 0
db 0
db 10010010b ;present, dpl 0, non-system, type data/read/write (02h)
db 11001111b ;g=1, d/b=1
db 0

gdtVideo: ;Video Memory Descriptor (3) 64k
dw 0ffffh
dw 08000h
db 0Bh
db 10010010b
db 00000000b
db 0

gdt_end:


; --------------------------------------------
;  Here is the entry point
; --------------------------------------------
begin:
mov ax, cs ; Get the current segment
mov ds, ax ; The data is in this segment
cli ; disable interrupts while changing stack
mov ss, ax ; We'll use this segment for the stack too
mov sp, 0xfffe ; Start the stack at the top of the segment
sti ; Reenable interrupts

mov ax, 0xb800
mov es, ax
mov ax, 0x0749  ;white "I"
mov [es:0], ax
xor ah, ah
int 0x16        ;pause for key

cli

lgdt [gdtr]

mov eax, cr0
or eax, 1
mov cr0, eax

jmp 1*8:pmresume

bits 32

pmresume:

; mov ax, 2*8 ;data segment
; mov ds, ax
mov ax, 3*8 ;video segment
mov es, ax

mov word [es:0], 0x0748     ;white "H"

jmp $
jamethiel

RE:switching to pmode problem...

Post by jamethiel »

The first thing that comes to mind is that unless this code is loaded at 0000:0000, the jump to pmresume is going to come out at the wrong place.

If this is a .COM file, add code to patch the GDT to the current segment (you may need to use the other granularity setting on that descriptor).
If this is a bootsector, set your assembly origin to the correct location.
osnewbie

RE:switching to pmode problem...

Post by osnewbie »

here is what i tried, it still reboots. the code is compiled to a .bin file on a floppy which boot12.asm loads to 1000:0000, which is 0x10000 physical address isn't it?? i am not very good with memory addresses yet, but since i thought that that was what it was, i added the +0x10000 to the pmode offsets just for testing purposes, but it still reboots... i dont know if it is in the gdt, or if i have memory addresses wrong or what, once again, i am new to this...

any ideas appreciated!!

--------------------------

org 0x0
jmp begin

bits 16

gdtr:
dw gdt_end-gdt-1
dd gdt

gdt:
gdt0: ;Null Descriptor (0)
dd 0
dd 0
gdtCode: ;Code Descriptor (1) 4GB
dw 0ffffh
dw 0
db 0
db 10011010b ;present, dpl 0, non-system, type code/execute/read (0Ah)
db 11001111b ;g=1, d/b=1
db 0

gdtData: ;Data Descriptor (2) 4GB
dw 0ffffh
dw 0
db 0
db 10010010b ;present, dpl 0, non-system, type data/read/write (02h)
db 11001111b ;g=1, d/b=1
db 0

gdtVideo: ;Video Memory Descriptor (3) 64k
dw 0ffffh
dw 08000h
db 0Bh
db 10010010b
db 00000000b
db 0

gdt_end:


; --------------------------------------------
;  Here is the entry point
; --------------------------------------------
begin:
mov ax, cs ; Get the current segment
mov ds, ax ; The data is in this segment
cli ; disable interrupts while changing stack
mov ss, ax ; We'll use this segment for the stack too
mov sp, 0xfffe ; Start the stack at the top of the segment
sti ; Reenable interrupts

mov ax, 0xb800
mov es, ax
mov ax, 0x0748
mov [es:0], ax
xor ah, ah
int 0x16

cli

lgdt [gdtr]

mov eax, cr0
or eax, 1
mov cr0, eax

jmp dword 1*8:(pmresume+0x10000)

bits 32

pmresume:

mov ax, 2*8 ;data segment
mov ds, ax
mov gs, ax
mov fs, ax
mov ss, ax
mov sp, 0x9000
mov bp, sp

mov ax, 3*8 ;video segment
mov es, ax


mov word [es:2], 0x0749

halt:
jmp (halt+0x10000)
osnewbie

one more thing...

Post by osnewbie »

i also think i read somewhere about having to "code the far jump by hand" to enter pmode or something? is my jump to pmresume coded correctly and is it a far jump, or do i have to explicitly say its a far jump? if so how? and what is the difference anyway???

thanks
Khumba

RE:switching to pmode problem...

Post by Khumba »

I am __horrible__ at pmode, but try this. I had this problem when I first tried pmode. The pointer to the GDT (gdtr) is not relative, so you might need to change "dd gdt" to "dd gdt+BASEADDRESS".
max

RE:switching to pmode problem...

Post by max »

hi -

I wrote an OS not too long ago. You have a well-known symptom here: your machine reboots because your selectors are not well set OR because your didn't make the proper jmp statement. Anyway. it all leads to triple faulting the CPU = reboot with no warnings, no error message.

I don't have time to explain how to switch to protected mode. All I can tell you is that you need to look at this code : http://www.osdev.org/developers/guide01/loader.asm

it's a kernel loader written in NASM - BTW from this website (maybe you should have looked around before asking....)

it's very well written and pretty self explanatory.

pmode is easy once you understand which address represents what. if your PC-memory addressing ability is weak, then you definitely need to pratice asm before even thinking about pmode. sorry ;)

max
Osnewbie

RE:switching to pmode problem...

Post by Osnewbie »

The thing is that i did look around before posting, in fact i downloaded 3 different nasm examples, compiled them, and each one rebooted my computer. one thing i did notice is that in the list files from nasm the org xxx did not change anything. i did a little test:

org 0x0
dd 0xffffffff
here:
dd 0x88888888
dd here

and in the list it came up with 00000004 for 'here'

when i changed the org to org 0x7c00, the list file was exactly the same. so does dd here just store the relative address from the beginning of the program? and if so what good is org? either way, i tried adding the base address to the dd gdt line and it still kept rebooting...
i have also tried changing the jmp 1*8:pmresume to jmp 1*8:pmresume+BASEADDRESS and jmp dword 1*8:pmresume+BASEADDRESS which still rebooted...
pepito

RE:switching to pmode problem...

Post by pepito »

I belive that you can not access the GDT because the GDT BASE must be an
absolute address:

gdtr:
dw gdt_end-gdt-1
dd gdt ; <-- This is an offset, not absolute address!

In addition you are jumping out of your own program because your Code Descriptor have a BASE=0 but your program is not there (0000:0000). Then you never find the lines:

mov ax, 3*8 ;video segment
mov es, ax
mov word [es:0], 0x0748 ;white "H"

Try this (after you write the "I" char):

; Get the absolute address of your program (where you like to jump)
xor ebx, ebx
mov bx, ds ; Try too: mov bx, cs
shl ebx, 4
mov eax, ebx

; Update the BASE of the Code Descriptor and Data Descriptor
mov [gdtCode + 2], ax
mov [gdtData + 2], ax
shr eax, 16
mov [gdtCode + 4], al
mov [gdtData + 4], al
mov [gdtCode + 7], ah
mov [gdtData + 7], ah

; Update the address of the GDT
lea eax, [gdt + ebx]
mov [gdtr + 2], eax  

; Switch to protected mode
cli
lgdt [gdtr] ; Load the GDT register  
mov eax, cr0
or eax, 1
mov cr0, eax ; Active protected mode
jmp 1*8:pmresume ; Now you are really jump to the pmresume: label

I am new with protected mode too and this code is not mine, I get it from a Cristopher Giese demo at http://www.execpc.com/~geezer/os (now idle).
Post Reply