Pmode, what a surprise

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
User avatar
Zacariaz
Member
Member
Posts: 1069
Joined: Tue May 22, 2007 2:36 pm
Contact:

Pmode, what a surprise

Post by Zacariaz »

So i have been reading the osdev tut at brokenthorn.com but one i need answered.

Code: Select all

bits	16

org		0x7c00

start:
	jmp	loader

gdt_data: 
	dd 0 				; null descriptor
	dd 0 

; gdt code:				; code descriptor
	dw 0FFFFh 			; limit low
	dw 0 				; base low
	db 0 				; base middle
	db 10011010b 			; access
	db 11001111b 			; granularity
	db 0 				; base high

; gdt data:				; data descriptor
	dw 0FFFFh 			; limit low (Same as code)10:56 AM 7/8/2007
	dw 0 				; base low
	db 0 				; base middle
	db 10010010b 			; access
	db 11001111b 			; granularity
	db 0				; base high

end_of_gdt:
toc: 
	dw end_of_gdt - gdt_data - 1 	; limit (Size of GDT)
	dd gdt_data 			; base of GDT

loader:
	xor	ax, ax
	mov	ds, ax
	mov	es, ax

	cli
	lgdt 	[toc]

	hlt
	
times 510 - ($-$$) db 0

dw 0xAA55
Does this actually put the computer in to 32bit pmode?

Yes i know a20 hasnt been enabled and all that, but from what ive read this is really all there is to it, when only considering entering 32bit pmode, and i find that very hard to believe.
This was supposed to be a cool signature...
User avatar
AJ
Member
Member
Posts: 2646
Joined: Sun Oct 22, 2006 7:01 am
Location: Devon, UK
Contact:

Post by AJ »

Hi,

Yes - that's pretty much all there is to it.

As you say, you need to enable A20 and once you have done the jump to pmode you will need an IDT and TSS if you plan to handle interrupts / multitask, but all that is done once you are in PMode - run it in Bochs and you will notice that the final register dump will say 'Protected Mode'.

Cheers,
Adam

[EDIT]Damn - you aren't in PMode - you havent set the PE bit in CR0![/EDIT]
User avatar
Zacariaz
Member
Member
Posts: 1069
Joined: Tue May 22, 2007 2:36 pm
Contact:

Post by Zacariaz »

ah! i knew there was something i had overlooked, ill be right back ;)
This was supposed to be a cool signature...
User avatar
Zacariaz
Member
Member
Posts: 1069
Joined: Tue May 22, 2007 2:36 pm
Contact:

Post by Zacariaz »

so the lines that are missing is:

Code: Select all

	mov	eax, cr0
	or	eax, 1
	mov	cr0, eax
and then it should be in 32bit pmode, allthough with messed up segmentregister and no a20.
Correct?

edit: You know youre in pmode when you triplefault as you re-enable interrupts ;)
This was supposed to be a cool signature...
cyr1x
Member
Member
Posts: 207
Joined: Tue Aug 21, 2007 1:41 am
Location: Germany

Post by cyr1x »

AFAIK you also need to do a far-jump
e.g.

Code: Select all

jmp 0x08(or some other codesegment):somelocation
User avatar
neon
Member
Member
Posts: 1567
Joined: Sun Feb 18, 2007 7:28 pm
Contact:

Post by neon »

Hey,

While the code is correct, it does not touch pmode at all. You need to set the PMode bit in cr0 to enter protected mode. From here, CS will still contain the segment value (Probably still 0x7c0), which is bad. Because of this, you need to reset CS to your code descriptor offset (0x8) by far jumping:

Code: Select all

; make sure to disable interrupts before entering pmode, and do not
; re-enable them until you have a valid IDT.
cli

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

; we are now in pmode. Far jump to reset CS

jmp 0x8:Stage3

bits 32

Stage3:

; Welcome to 32bit world
Also, you dont *need* a20 to enter protected mode, however it is recommended.
OS Development Series | Wiki | os | ncc
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
User avatar
Zacariaz
Member
Member
Posts: 1069
Joined: Tue May 22, 2007 2:36 pm
Contact:

Post by Zacariaz »

is there a difference between enabling A20 before and after Pmode?

Here is the code so far:

Code: Select all

bits	16

org		0x7c00

start:
	jmp	stage1

gdt_data: 
	dd 0 				; null descriptor
	dd 0 

; gdt code:				; code descriptor
	dw 0FFFFh 			; limit low
	dw 0 				; base low
	db 0 				; base middle
	db 10011010b 			; access
	db 11001111b 			; granularity
	db 0 				; base high

; gdt data:				; data descriptor
	dw 0FFFFh 			; limit low (Same as code)10:56 AM 7/8/2007
	dw 0 				; base low
	db 0 				; base middle
	db 10010010b 			; access
	db 11001111b 			; granularity
	db 0				; base high

end_of_gdt:
toc: 
	dw end_of_gdt - gdt_data - 1 	; limit (Size of GDT)
	dd gdt_data 			; base of GDT

stage1:
	xor	ax, ax
	mov	ds, ax
	mov	es, ax

	cli
	lgdt 	[toc]
	mov	eax, cr0
	or	eax, 1
	mov	cr0, eax
	jmp	0x8:stage2
stage2:
	hlt
	
times 510 - ($-$$) db 0

dw 0xAA55
This was supposed to be a cool signature...
User avatar
lukem95
Member
Member
Posts: 536
Joined: Fri Aug 03, 2007 6:03 am
Location: Cambridge, UK

Post by lukem95 »

if you enter it before i believe you are entering unreal mode briefly, although i dont think this matters.

also i've seen code that does both, i dont think there is a difference.
~ Lukem95 [ Cake ]
Release: 0.08b
Image
User avatar
neon
Member
Member
Posts: 1567
Joined: Sun Feb 18, 2007 7:28 pm
Contact:

Post by neon »

There is no difference.

The only thing wrong with the code is the exclusion of bits 32. (Please see my previous example.) Everything else looks fine.
OS Development Series | Wiki | os | ncc
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
User avatar
bewing
Member
Member
Posts: 1401
Joined: Wed Feb 07, 2007 1:45 pm
Location: Eugene, OR, US

Post by bewing »

And, of course, once you are in PMODE, the BIOS no longer works. So you can't read anything else into memory with an INT command. So, unless you have all your data, or a disk driver in memory, you're stuck at that point.

And, of course, you really want to gather all the BIOS info that you can, before that point ... especially regarding memory and VBE info (and maybe PCI, and floppy, and etc. too).
User avatar
Zacariaz
Member
Member
Posts: 1069
Joined: Tue May 22, 2007 2:36 pm
Contact:

Post by Zacariaz »

for now im just interested in getting into long mode (while understanding the process). I dont intent to make anything that should be able to run on other than my own machine (and qemu) which shouldnt be a problem.
Thus, i dont need to get the size of the memory as i always know it. Nor do i need any info about pci or anything else. Well, i need to read/write the disk (usb or hdd or maybe even lan, but i dont believe ill be able to do the usb/lan stuff) but ill take that up later when i understand the process better.

And kudos to brokenthorn.com, its really an amazing os tut.
This was supposed to be a cool signature...
User avatar
AJ
Member
Member
Posts: 2646
Joined: Sun Oct 22, 2006 7:01 am
Location: Devon, UK
Contact:

Post by AJ »

Hi,

There is a difference between enabling A20 before or after you enter PMode. Because of the way the address lines are wired up, I believe that some systems prevent you accessing every other MiB if you don't enable it before you go to PMode (you can't access 2-3Mib, 4-5Mib etc...). Someone else may be able to furnish you with the details of this, but it's safer to enable A20 first.

Cheers,
Adam
User avatar
Zacariaz
Member
Member
Posts: 1069
Joined: Tue May 22, 2007 2:36 pm
Contact:

Post by Zacariaz »

thats good to know.
This was supposed to be a cool signature...
User avatar
bewing
Member
Member
Posts: 1401
Joined: Wed Feb 07, 2007 1:45 pm
Location: Eugene, OR, US

Post by bewing »

I'm not sure about qemu, but bochs always has the A20 line enabled. You do not have to do it yourself in bochs. Your PC may be the same. Just for fun, here is my A20 code.

(Written for NASM. Public domain. Interrupts need to be off, I think. It compiles, and should run fine. It needs timeouts in all the wait loops, of course.)
Attachments
A20.TXT
(3.47 KiB) Downloaded 31 times
Last edited by bewing on Mon Jan 21, 2008 7:19 pm, edited 1 time in total.
sancho1980
Member
Member
Posts: 199
Joined: Fri Jul 13, 2007 6:37 am
Location: Stuttgart/Germany
Contact:

Post by sancho1980 »

lukem_95 wrote:if you enter it before i believe you are entering unreal mode briefly, although i dont think this matters.

also i've seen code that does both, i dont think there is a difference.
AFAIK, unreal mode is when you enter pm, set your segments' bases to 0 and their limits to maximum and then return to real mode, so that you can address you full memory in real mode (which makes it so "UN"real)
Post Reply