Page 1 of 2

Unreal Mode - Problem

Posted: Wed Oct 15, 2008 3:44 pm
by Wolftein
Hello, I´m Developing my own BootLoaded.. i need help, what im doing wrong here?

1) Goto ProtectMode
2) Back To RealMode
3) Set ES To Read With Selector That Point To Base Adddr 0, but insteant it point to 80 Why Its That?

Here Its The Code...

Code: Select all

	 PROCESSOR_setvoodomode:
			 
			 SMSW AX
			 TEST AL,0x1
			 JE   .STARTUNREAL
			 
			 XSystemCriticalError PROC_ALREADYPM
	   .STARTUNREAL:
			 XOR EAX,EAX
			 MOV AX,CS
			 
			 SHL EAX,0x4
			 MOV WORD[DS:SYS_CODE + 2],AX
			 MOV WORD[DS:SYS_DATA + 2],AX
			 MOV WORD[DS:REAL_CODE + 2],AX
			 MOV WORD[DS:REAL_DATA + 2],AX

			 ;Set Physical Lineal Address
			 LEA EBX,[GDT + EAX]
			 MOV DWORD[GDT_START+2],EBX 
			 
			 SHR EAX,0x10
			 MOV BYTE[DS:SYS_CODE + 4],AL
			 MOV BYTE[DS:SYS_DATA + 4],AL
			 MOV BYTE[DS:REAL_CODE + 4],AL
			 MOV BYTE[DS:REAL_DATA + 4],AL

			 MOV BYTE[DS:SYS_CODE + 7],AH
			 MOV BYTE[DS:SYS_DATA + 7],AH
			 MOV BYTE[DS:REAL_CODE + 7],AH
			 MOV BYTE[DS:REAL_DATA + 7],AH
			 
			 CLI
			 
			 LGDT [GDT_START]
		  
			 MOV BP,CS			;Save The CS In BP
			 
			 MOV EAX,CR0
			 OR  AL,0x1
			 MOV CR0,EAX
			 
			 JMP SYS_CODE_SEL:DO_PROTECTMODE
	    [BITS 32]
		DO_PROTECTMODE:
			 MOV AX,SYS_DATA_SEL
			 MOV DS,AX
			 MOV SS,AX
			 MOV ES,AX
			 MOV FS,AX
			 MOV GS,AX
			 
			 JMP REAL_CODE_SEL:DO_REALMODE
		[BITS 16]
		DO_REALMODE:
			 MOV AX,REAL_DATA_SEL
			 MOV DS,AX
			 MOV SS,AX
			 
			 LEA BX,[DO_UNREAL]
			 
			 PUSH BP
			 PUSH BX
			 
			 MOV EAX,CR0
			 AND AL,0xFE
			 MOV CR0,EAX

			 
			 RETF
	   [BITS 16]
		DO_UNREAL:
			 
			 MOV AX,CS
			 MOV DS,AX
			 MOV ES,AX
			 MOV FS,AX
			 MOV GS,AX
			 
			 MOV AX,LDRSTACKSEGMENTLOCATION
			 MOV SS,AX

			 STI
			 
			 RET


[BITS 32]
;; Global Descriptor Table & Interrump Descriptor Table
GDT_START: DW (GDT_END - GDT - 1)
		   DD (LDRCODESEGMENTSIZE + GDT)
		 
IDT_START: DW (IDT_END - IDT - 1)
		   DD (LDRCODESEGMENTSIZE + IDT)
		 
		 
GDT:			   ;0x0
	DW 0x0000
	DW 0x0000
	DB 0x00
	DB 0x00
	DB 0x00
	DB 0x00
LINEAL_DATA_SEL		EQU	$-GDT ;0x8
LINEAR_SEL:
	DW 0xFFFF
	DW 0x0000
	DB 0x00
	DB 0x92
	DB 0xCF
	DB 0x00
SYS_CODE_SEL	EQU	$-GDT ;0x10
SYS_CODE:
	DW 0xFFFF
	DW 0x0000
	DB 0x00
	DB 0x9A
	DB 0xCF
	DB 0x00
SYS_DATA_SEL	EQU	$-GDT ;0x18
SYS_DATA:
	DW 0xFFFF
	DW 0x0000
	DB 0x00
	DB 0x92
	DB 0xCF
	DB 0x00
REAL_CODE_SEL	EQU	$-GDT ;0x20
REAL_CODE:
	DW 0xFFFF
	DW 0x0000
	DB 0x00
	DB 0x9A
	DB 0x00
	DB 0x00
REAL_DATA_SEL	EQU	$-GDT ;0x28
REAL_DATA:
	DW 0xFFFF
	DW 0x0000
	DB 0x00
	DB 0x92
	DB 0x00
	DB 0x00
STAGE2_CODE_SEL EQU $-GDT ;0x30
STAGE2_CODE:
	DW 0xFFFF
	DW 0x9000
	DB 0x01
	DB 0x9A
	DB 0xCF
	DB 0x00
STAGE2_DATA_SEL EQU $-GDT
STAGE2_DATA:
	DW 0xFFFF
	DW 0x9000
	DB 0x01
	DB 0x92
	DB 0xCF
	DB 0x00
	
GDT_END:

[SEGMENT .bss]
IDT:
	RESB 256*8
IDT_END:

            -----------
            MOV EDI,0x19000
            MOV AX,0x8
            MOV ES,AX -> BASE ADDR OF ES ITs 80 :S
            MOV EAX,[ES:EDI] -> I Want To Read 0x0:0x19000 
Thanks you :)

Re: Unreal Mode - Problem

Posted: Wed Oct 15, 2008 4:06 pm
by Combuster
if you load ES with the value 8, then of course its base gets set to 8 * 16 = 0x80.

Re: Unreal Mode - Problem

Posted: Wed Oct 15, 2008 4:18 pm
by Wolftein
Combuster wrote:if you load ES with the value 8, then of course its base gets set to 8 * 16 = 0x80.
Unreal mode doesn´t work like protected mode? I Thought That Setting ES = 0x8 Will Set With The BaseAddr Of Descriptor One...

Re: Unreal Mode - Problem

Posted: Wed Oct 15, 2008 4:39 pm
by Combuster
Unreal mode is technically real mode with a processor glitch in place that causes it to ignore the segment size

Re: Unreal Mode - Problem

Posted: Fri Oct 17, 2008 4:09 am
by jal
Combuster wrote:Unreal mode is technically real mode with a processor glitch in place that causes it to ignore the segment size
I wouldn't call it a glitch as it is used by SMM as well. All processors support it (it may have been a glitch on the 386, but it certainly isn't now).


JAL

Re: Unreal Mode - Problem

Posted: Fri Oct 17, 2008 4:14 am
by jal
Wolftein wrote:Unreal mode doesn´t work like protected mode?
No it doesn't. Unreal mode works like real mode (in fact, it is real mode), hence the name.
I Thought That Setting ES = 0x8 Will Set With The BaseAddr Of Descriptor One...
You should never change the segment registers, as it will change their limit back to 64Kb (the normal value in real mode).

What happens when setting up unreal mode, is that you go to protected mode and set the segment registers there, with a limit of 4Gb. When you go back to real mode (and make no mistake, you are in plain real mode, never mind the 'unreal mode' moniker), the segment registers still have their protected mode value and limit, which is what you want. However, when changing any of the segment registers, the CPU resets their limit to 64Kb, which is what you don't want. Therefore you cannot change any of the segment registers when you are into unreal mode, as that breaks it.


JAL

Re: Unreal Mode - Problem

Posted: Fri Oct 17, 2008 4:29 am
by CodeCat
What would normally happen if you set eax to 0x100000 in real mode and then dereferenced that? GPF?

Re: Unreal Mode - Problem

Posted: Fri Oct 17, 2008 6:16 pm
by pcmattman
The address would wrap, iirc.

Re: Unreal Mode - Problem

Posted: Fri Oct 17, 2008 6:39 pm
by CodeCat
That would be if gate A20 was not enabled, yes. But would it still wrap if it were enabled?

Re: Unreal Mode - Problem

Posted: Sat Oct 18, 2008 4:11 am
by Combuster
In real mode, the segment limit is normally 64k. That means if you force 32-bit addressing (via mov [eax], ...) then it will try to use the 32-bit size and check it against the segment limit. if EAX happens to be 0x10000 or higher then it is outside the 64k range (0x0000 - 0xFFFF) and a segment violation is reported via the GPF

Only after when the processor decides that the address is valid, then it computes base + offset and puts that through to the data bus (and only here will A20 be applied, so the GPF will occur irrespective of whether A20 is enabled or not)

In unreal mode, the segment limit is not the usual 64k, but a different (usually higher) value so that 32-bit addresses over 64k no longer cause that GPF but get executed instead (allowing access to memory well above real mode's 1M limit)

Another thing of unreal mode is that the limit doesn't get reset to 64k upon a write to a segment register - instead it is preserved.

Re: Unreal Mode - Problem

Posted: Sat Oct 18, 2008 4:55 pm
by Masterkiller
jal wrote:You should never change the segment registers, as it will change their limit back to 64Kb (the normal value in real mode).
That's not true. Hidden part of the segments is not affected by processor if bit 0 on CR0 is not set (e.g. system is in real mode). Actually you should set visible part of the segment registers to 0, after you are in unreal mode, or you will never have exact address.
If bit 0 on CR0 is not set, physical addresses are made by following formula:

Code: Select all

(DWORD)BASE + (WORD)SEGMENT*16 + (WORD/DWORD)OFFSET
BASE - base address of the descriptor loaded in hidden part of the segment.
SEGMENT - value of the visible part of the segment.
OFFSET - value by the instruction.
So in most case it is REQUIRED to change the visible part of the segment in unreal mode, to get proper address.

Re: Unreal Mode - Problem

Posted: Sun Oct 19, 2008 10:38 am
by Combuster
Masterkiller wrote:If bit 0 on CR0 is not set, physical addresses are made by following formula:

Code: Select all

(DWORD)BASE + (WORD)SEGMENT*16 + (WORD/DWORD)OFFSET
That can't be true - look at CS, once you disable the PE bit you'd suddenly get an additional CS*16 added to your offset, misaligning any code (and therefore blocking any sane attempt to return from protected mode since you can't set CS to null there)

Instead in real mode when you set a segment register you reload the segment's base register in the hidden portion, so that the formula that holds in protected mode holds too for real mode:

Code: Select all

(DWORD)BASE + (WORD/DWORD)OFFSET
and upon changing segment:

Code: Select all

if (real_mode)
   base = selector * 16
else
   base = GDT[selector].base     // or LDT or exception or whatever

Re: Unreal Mode - Problem

Posted: Sun Oct 19, 2008 11:06 am
by Masterkiller
Combuster wrote:
Masterkiller wrote:If bit 0 on CR0 is not set, physical addresses are made by following formula:

Code: Select all

(DWORD)BASE + (WORD)SEGMENT*16 + (WORD/DWORD)OFFSET
That can't be true - look at CS, once you disable the PE bit you'd suddenly get an additional CS*16 added to your offset, misaligning any code (and therefore blocking any sane attempt to return from protected mode since you can't set CS to null there)
Actually CS is not verified when fetching instruction and even changes the CPU mode. It is veryfied once if changed. In that way CPU is able to execute first JMP when enters Protected mode. Even more if you are in address 0x1000:0x0002 and instruction there enters Protected Mode, next instruction will be always 0x10004 and then 0x10006 (depeneds on the size of previous instruction). The same is when returns in real mode. Seems Base address that real and protected mode segment is not checked on changing mode, only when you reload segment. (I've tested in on real hardware).
Combuster wrote:Instead in real mode when you set a segment register you reload the segment's base register in the hidden portion, so that the formula that holds in protected mode holds too for real mode:

Code: Select all

(DWORD)BASE + (WORD/DWORD)OFFSET
and upon changing segment:

Code: Select all

if (real_mode)
   base = selector * 16
else
   base = GDT[selector].base     // or LDT or exception or whatever
Well, again I say that why you are in REAL mode, hidden part of the segment is never reloaded. You actually do not have GDT in real mode.
When I've first tested writing to video buffer in 32-bit SVGA mode, my DS was also 0x1000 on entering UNREAL mode. Then I start loop writing to 0xD8000000 (start of SVGA Buffer). First several lines from the screen were empty. I thought it is a bug from bochs and tested it at real hardware, but the same result. Actually instruction writing to 0xD8010000 because of the visible part of the segment, and because while CPU is in real mode, this part is multiplied by 16 and added to address. Zero the visible part in unreal mode before using the segment fixed that.

Re: Unreal Mode - Problem

Posted: Sun Oct 19, 2008 1:03 pm
by i586coder
UNREAL MODE or FLAT-real mode whatever :lol:

it's cooool trick to access all available memory up to 4 gigs
specially for people those can't understanding PM well like ME #-o
who is care :mrgreen:

to enter FLAT-mode
1. goto PM & change some values in GDT
2. return to real mode
3. ahhhh, now you can use mov eax, {pointer to your data}

use this link
http://www.ddci.com/display_article-art ... _10040.php
i used it when i coded my UNEXT/os v4.5

8)

Re: Unreal Mode - Problem

Posted: Sun Oct 19, 2008 4:45 pm
by CodeCat
PM isn't that hard. If you use two flat descriptors for code and data, don't enable paging, set up an IDT and keep all code in ring 0, it's almost like real mode, but better. :D