Page 2 of 2

Posted: Fri Apr 04, 2008 4:04 am
by jal
Ready4Dis wrote:I jump back and forth between r-mode and unreal mode (flat real mode) while loading
Ehmm... I hope this doesn't mean what it seems to mean. Flat real is just real mode. You can do anything you can also do in real mode, and of course a bit more. There's no need to go jumping (let alone back and forth).


JAL

Posted: Fri Apr 04, 2008 7:16 am
by Ready4Dis
jal wrote:
Ready4Dis wrote:I jump back and forth between r-mode and unreal mode (flat real mode) while loading
Ehmm... I hope this doesn't mean what it seems to mean. Flat real is just real mode. You can do anything you can also do in real mode, and of course a bit more. There's no need to go jumping (let alone back and forth).


JAL
I'm affraid it does man, I switch back and forth between the two, they are NOT identical, and there is no gaurantee that the bios interrupts won't touch your segment registers, so you can't gaurantee that the calls will work properly. Unless I missed something, reloading ds or es will cause you to leave unreal mode, and who's to say that bios interrupts don't do this? A simple push/pop can cause it, or sometimes the bios functions run in pmode (16-bit or 32-bit), so they would hose up unreal mode. I know this isn't common practice, but it does happen, and I'd rather just avoid it. I wrote a copy32 function that takes esi,edi and ecx, sets the pmode flag, reloads ds,es, does the rep movsd call, then clears the pmode flag, pop's ds/es and returns. I know, most bios interrupts avoid changing these registers, and avoid trying to change modes, since they have to work in vm86 mode, so I may switch back to the other method, but for now this works and is fast enough.

--- Edit ---
Well, after a bit of thinking, i'm pretty sure most bios functions won't touch ds, since it would break vm86 mode. so I will probably change my method soon, however, interestingly, I realized I am doing the rep movsd call before clearing the pmode bit, so I actually don't know what state the cpu thinks it's in, but it has the 16-bit real-mode CS in there, and 32-bit DS/ES, i need to do an a32 rep movsd call (rather than a regular rep movsd), so possibly I have something messed up (however it works, but I think I am going to set unreal mode in the beginning and just assume it won't get hosed).

Posted: Fri Apr 04, 2008 7:45 am
by jal
Ready4Dis wrote:Unless I missed something, reloading ds or es will cause you to leave unreal mode
Quoting the Wiki:
OSDevWiki wrote:After the switch back to real mode, these values are not modified, regardless of what value is in the 16-bit segment register. So the 64k limit is no longer valid and 32-bit offsets can be used with the real-mode addressing rules (i.e. shift segment 4 bits, then add offset).
So it seems you have indeed missed something, or I am interpreting the Wiki in a wrong way.


JAL

Posted: Fri Apr 04, 2008 8:11 am
by Ready4Dis
If reloading the segment register does nothing, then why would it do something when you set the pmode flag, since when pmode flag is set, you don't do a far jump to reload CS or anything, so why would changing DS/ES in there modify the descriptor? Anyways, I am probably going to re-write my code knowing this, not that it's going to make a huge difference, as i'm sure the disk latency is more of an issue than the switching, but faster is better! Reading the wiki, I definetly missed something, I see that loading the segments registers in pmode affects the limit, while reloading them in rmode doesn't, so I will fix up my bootloader one of these days to work 'properly', thanks for the info.

Posted: Sat Apr 05, 2008 12:37 am
by jal
Ready4Dis wrote:Reading the wiki, I definetly missed something, I see that loading the segments registers in pmode affects the limit, while reloading them in rmode doesn't, so I will fix up my bootloader one of these days to work 'properly', thanks for the info.
You're welcome. In realmode the limits are used, but not affected when loading segments. And yes, I think disk overhead will probably take much more time than the switching, but that's indeed no excuse for slow code :).


JAL

Posted: Sat Apr 05, 2008 1:02 am
by Ready4Dis
jal wrote:
Ready4Dis wrote:Reading the wiki, I definetly missed something, I see that loading the segments registers in pmode affects the limit, while reloading them in rmode doesn't, so I will fix up my bootloader one of these days to work 'properly', thanks for the info.
You're welcome. In realmode the limits are used, but not affected when loading segments. And yes, I think disk overhead will probably take much more time than the switching, but that's indeed no excuse for slow code :).
JAL
Yeah, and again, thanks for the info, I originally tried it this way, and it kept failing, so once I got it working I just stopped. I went back in yestarday and fixed it up, and now it sets unreal mode and leaves it there until going pmode. Right now I have it load one sector, copy 1 sector, repeat, I will probably change it to load multiple sectors, then copy multiple, splitting it up depending on space availability, but it runs fine for now, many more important things to work on than making my bootloader load the kernel .1 seconds faster, and probably growing another 100 bytes, meaning it'd run into the next sector (It currently uses 2 sectors, but it's close to the 1024 limit now, around 975 bytes, not that it really matters, since my formatter automatically allocates and sets reserved sectors properly depending on its size).

Posted: Sat Apr 05, 2008 4:42 am
by Pitchu
Ok
So it means I should use Un-Real Mode for loading kernel if it doesnt fit in 1MB space.

So far as doing a research over minimum number of GDT enteries is concerned, I came to conclusion that DATA descriptor will also be used as STACK desriptor........Sounds silly only for one reason that stack grows downwards, what do you say?

Posted: Sat Apr 05, 2008 5:03 am
by jal
Pitchu wrote:Ok
So it means I should use Un-Real Mode for loading kernel if it doesnt fit in 1MB space.
That's the easiest way, as you needn't switch between PM and real mode then.
So far as doing a research over minimum number of GDT enteries is concerned, I came to conclusion that DATA descriptor will also be used as STACK descriptor
That's what most people do, yes.
Sounds silly only for one reason that stack grows downwards, what do you say?
I'm not sure why you think that is silly. The idea is that you have two selectors (one code, one data) that encompas the entire 4GB address limit. Protection is done by paging.


JAL

Posted: Sat Apr 05, 2008 5:06 am
by Ready4Dis
Minimum entries to enter unreal mode is 1 entry, it is used for loading ds (and any other segment register you wish to use, typically es as well for things like rep movs(b,w,d), etc.)

Nasm code for minimum unreal mode setup :)

Code: Select all

align 8   ;Make sure it's 8-byte aligned
gdt_start:  ;First entry (NULL entry is also our gdt descriptor!)
   dw gdt_end-gd_start
   dd gdt_start
   dw 0
;This is our DATA entry
   dw 0xffff
   dw 0x0000
   db 0x00
   db 10010010b
   db 11001111b
   db 0x00
gdt_end:

;Sets up ds/es for 4gb limit
SetupUnreal:
   push eax
   push bx
   push ds
   push es
   lgdt [gdt_start]
   mov eax, cr0   ;Grab CR0
   inc ax             ;Set pmode bit
   mov cr0, eax   ;Move back into CR0
   mov bx, 0x08  ;Data descriptor
   mov ds, bx
   mov es, bx
   dec ax            ;Unset pmode bit
   mov cr0, eax  ;Move back into CR0
   pop es
   pop ds
   pop bx
   pop eax
   ret
So, after this is called, you can do this:

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

And it will print the letter A to the screen at linear address 0xb8000, rather than having to do the segment + offset thing :) Just make sure ds is 0x0000.

--- Edit ---
Fixed up something, forgot to lgdt ;).

Posted: Sat Apr 05, 2008 5:31 am
by Pitchu
I'm not sure why you think that is silly. The idea is that you have two selectors (one code, one data) that encompas the entire 4GB address limit. Protection is done by paging
I am confused with the fact that 4 bits of the first DWORD of descriptor (i.e. b8 to b11) meant for Segment TYPE has a bit that defines whether a segment expands downwards(meant for STACK) or upwards.
Pal......what to put in there or i messing this up? :roll:

Posted: Sat Apr 05, 2008 6:01 am
by jal
Pitchu wrote:I am confused with the fact that 4 bits of the first DWORD of descriptor (i.e. b8 to b11) meant for Segment TYPE has a bit that defines whether a segment expands downwards(meant for STACK) or upwards.
Pal......what to put in there or i messing this up? :roll:
Upwards. Since you define the entire 4GB as one segment, there's no expanding. That's just for segmentation, but that's legacy.


JAL

Posted: Sat Apr 05, 2008 9:05 am
by Pitchu
Pal....Thanks alot :D
I was messing PUSH and POP instructions with growth of segment forgetting that i am using flat model.
This is what happens when a Rmode Programmer comes to Pmode world.

Code: Select all

;Sets up ds/es for 4gb limit 
SetupUnreal: 
   push eax 
   push bx 
   push ds 
   push es 
   lgdt [gdt_start] 
   mov eax, cr0   ;Grab CR0 
   inc ax             ;Set pmode bit 
   mov cr0, eax   ;Move back into CR0 
   mov bx, 0x08  ;Data descriptor 
   mov ds, bx 
   mov es, bx 
   dec ax            ;Unset pmode bit 
   mov cr0, eax  ;Move back into CR0 
   pop es 
   pop ds 
   pop bx 
   pop eax 
   ret
Dont we need to enable A20?

Posted: Sat Apr 05, 2008 11:19 pm
by Ready4Dis
Yes, I assume if you're using pmode (why else would you load your kernel over 1mb?) you already have A20 enabling code in place. Sorry for not mentioning this for anyone trying to get unreal mode working before enabling A20, in my bootloader the A20 is enabled at the start, because if it can't be enabled, no point in going any further, and most people that use grub have the A20 enabled there, so it's not much of a point most of the time, however it is worth mentioning to people just starting out, or who have written their own bootloaders.

Posted: Sun Apr 06, 2008 5:54 am
by Pitchu
Thanks everybody
I will first put my hands on Unreal Mode and try to load some pseudo-kernel into memory.
Later, I will continue the thread while developing my Kernel.
Once more, Thanks
LOL