flat assembler
Message board for the users of flat assembler.

Index > DOS > What will an unreal mode segment register look like?

Author
Thread Post new topic Reply to topic
Cas



Joined: 26 Feb 2004
Posts: 82
Location: Argentina
Cas 29 Oct 2009, 06:43
Tell me if I'm right or wrong... or if I'm kind of right, but missing something, please...

If I want to set up unreal mode, I understand that things happen more or less this way:

- First, I'm in real mode, all my segment registers contain whatever they were being used with in that mode, so internally, and ideally, all of their bases are <=1MiB and all of their limits are exactly set to 64KiB as by default. Say I do MOV AX,DS at this point, AX will contain a value from 0000h to FFFFh, which could be physically "understood" as the segment base "div 16". In other words, segments look like their bases div 16 (that is, 3A21h for base 0003A210h in physical terms)
- Then, I switch to protected mode. I haven't touched the segment registers yet or created any table. If I do MOV AX,DS... what will I get stored in AX? I assume I will still be getting the same thing as when I was in real mode. However, when doing the opposite thing (MOV DS,AX) is when things changes and I need a selector, but again, reading from these registers still gives the same. Am I right?
- Now I set up the descriptors and trick the segments so that they have a 4GiB limit, but don't worry to change their bases. I assume, again, at this point, that by reading them with the MOV AX,DS instruction, I continue to get the same.
- Finally, I switch back to real mode and still are able to read the same values, except that now I can do something like MOV [DS:12345678h],AL without a problem. However there's one more step I am concerned about:
- Say now, still in real mode, I do MOV AX,0005h, and then MOV DS,AX. I understand the internal physical base in DS will be set to 00000050h and the limit automatically set back to 64KiB (as opposed to keeping the one I previously set). I also believe I am updating the whole base and not only the lower 20 bits of it, all the higher ones being set to zero. Am I right about this? Rolling Eyes

Thank you all very much for your help Smile

_________________
«Earth is my country; science is my religion» - Christian Huygens
Post 29 Oct 2009, 06:43
View user's profile Send private message Yahoo Messenger MSN Messenger Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20356
Location: In your JS exploiting you and your system
revolution 29 Oct 2009, 07:04
Cas wrote:
- Say now, still in real mode, I do MOV AX,0005h, and then MOV DS,AX. I understand the internal physical base in DS will be set to 00000050h and the limit automatically set back to 64KiB (as opposed to keeping the one I previously set).
The limit is not changed. That is why unreal mode works.
Post 29 Oct 2009, 07:04
View user's profile Send private message Visit poster's website Reply with quote
Cas



Joined: 26 Feb 2004
Posts: 82
Location: Argentina
Cas 30 Oct 2009, 03:01
Wow... now this is a whole change in my perspective! I thought applications in unreal mode had to keep a routine to trap exceptions when someone tried to address over 64KiB and then get the segment updated again... Thanks
What about the rest? Do segment registers always return bits 4 through 19 of the segment base no matter in which mode they are read?
Post 30 Oct 2009, 03:01
View user's profile Send private message Yahoo Messenger MSN Messenger Reply with quote
DOS386



Joined: 08 Dec 2006
Posts: 1903
DOS386 30 Oct 2009, 03:48
Cas wrote:

...

Welcome back Smile

revolution wrote:

Quote:
The limit is not changed. That is why unreal mode works.


Actually I also had ASS'um'ed the limit would get reset to 64 KiB on any write access to DS ... now I'm confused Sad
Post 30 Oct 2009, 03:48
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20356
Location: In your JS exploiting you and your system
revolution 30 Oct 2009, 04:52
Cas wrote:
Do segment registers always return bits 4 through 19 of the segment base no matter in which mode they are read?
Reading a segment register simply returns back the value you wrote to it previously, regardless of the mode. However, reading a memory address controlled by a segment register is an entirely different matter and can return completely different results depending upon the mode.
Post 30 Oct 2009, 04:52
View user's profile Send private message Visit poster's website Reply with quote
Cas



Joined: 26 Feb 2004
Posts: 82
Location: Argentina
Cas 01 Nov 2009, 10:20
Thank you, DOS386! I'm back with a new project which partially exceeds my current knowledge, so I am willing to learn everything I need to achieve it. If I say anything stupid or silly at anytime, please understand I'm learning. I won't stop this time. Smile
It is very important to me to make sure about the limit-reset thing. I can run the experiment myself, but it's complicated.
I have been poking into memory and I see that 4DOS does load something and hooks it with interrupt 6. When I read it, it looks like it verifies whether the A20 is enabled and then does some hocus-pocus. This sets me to think I probably was right at the beginning and that a procedure is required to keep the limit at 4GiB, but I still have no guarantee. Rolling Eyes

Revolution: By what you say, I understand that if I do this:

Code:
mov ax,1234h
mov ds,ax

call Set_up_a_running_PM_environment

mov ax,ds

call Return_to_RM
call Write_AX_to_the_screen_as_a_HEX
    


I will see the numbers "1234h", even though I have switched mode. Is that right?[/b]

_________________
«Earth is my country; science is my religion» - Christian Huygens
Post 01 Nov 2009, 10:20
View user's profile Send private message Yahoo Messenger MSN Messenger Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20356
Location: In your JS exploiting you and your system
revolution 01 Nov 2009, 11:40
Cas: The test should be easy to implement.
  1. set for unreal
  2. set a small print function on GPF fault handler
  3. mov ds,0x0000
  4. mov eax,[0x10000]
  5. if the handler prints something then your limit was changed
Also, there is no change in DS unless your code changes it. The CPU won't alter it automatically.
Post 01 Nov 2009, 11:40
View user's profile Send private message Visit poster's website Reply with quote
vid
Verbosity in development


Joined: 05 Sep 2003
Posts: 7105
Location: Slovakia
vid 01 Nov 2009, 16:25
cas: Besides the "DS" register you see, there are couple of "shadow" (hidden) registers that are not directly accessible. These are "segment base", "segment limit", and "segment access rights".

In protected mode, all "shadow" values are loaded from Global Descriprtor Table (GDT). This table is array of structures called "segment descriptor", and is indexed by value called "selector". When you move value to segment register, this value functions as selector. On move to segment register, CPU finds the descriptor indexed by this selector, and loads all "shadow" values from there.

Now, in real mode, CPU behaves differently. On every write to segment register, instead of using written value as selector, it shifts value left by 4, and writes it to segment base. Also, it supposedly *should* reset limit and access rights to real mode defaults (64k limit, dunno about rights). But the catch is that CPU doesn't do this, and that is why unreal mode (flat real mode) works. And this is 100% working everywhere, because it is used by BIOSes, many OSes, etc.

Clear?
Post 01 Nov 2009, 16:25
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
rugxulo



Joined: 09 Aug 2005
Posts: 2341
Location: Usono (aka, USA)
rugxulo 03 Nov 2009, 23:05
But if it's used by the BIOS, wouldn't using any BIOS int mess it up??
Post 03 Nov 2009, 23:05
View user's profile Send private message Visit poster's website Reply with quote
vid
Verbosity in development


Joined: 05 Sep 2003
Posts: 7105
Location: Slovakia
vid 04 Nov 2009, 02:37
AFAIK it is used by BIOS during pre-boot process only. Of course there may be implementation with protected mode, I don't claim this 100%ly.
Post 04 Nov 2009, 02:37
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
sinsi



Joined: 10 Aug 2007
Posts: 790
Location: Adelaide
sinsi 05 Nov 2009, 06:40
Some things can ruin your real-mode unreal stuff:
- himem.sys used unreal mode to copy extended memory
- lots of BIOSes used unreal mode for fn 87 'copy extended memory'
Since they took the time to restore things to proper real mode, your unreal mode code is trashed...
I have seen code where an int was hooked (0d?) to re-enable unreal mode and continue, in case a program changed things (as above).

One fun thing I remember is using edi=b8000 (video mem) and using gs to access it. I forgot to make gs=0 (it was 8 ) so all my writes to [gs:edi] were off by 1 line...


Last edited by sinsi on 05 Nov 2009, 07:06; edited 1 time in total
Post 05 Nov 2009, 06:40
View user's profile Send private message Reply with quote
Cas



Joined: 26 Feb 2004
Posts: 82
Location: Argentina
Cas 05 Nov 2009, 10:35
Razz
So say I want to install that trapping routine... there can be other reasons why int 0Dh could be triggered, no? Then should the routine check the stack to find the instruction address and then analyse the code to verify if it was actually a long address that caused the exception?!
It sounds like a lot of hassle to me. Do I instead just reset all segment registers' limits to 4GiB, go back to real mode and jump to the old exception handler?
Better... if anyone dares post a sample trapping routine here, I'll appreciate it Smile
Post 05 Nov 2009, 10:35
View user's profile Send private message Yahoo Messenger MSN Messenger Reply with quote
Japheth



Joined: 26 Oct 2004
Posts: 151
Japheth 05 Nov 2009, 12:20
Cas wrote:
Razz
Better... if anyone dares post a sample trapping routine here, I'll appreciate it Smile


You can look at the original Himem source. It's still available at the MS FTP server:

ftp://ftp.microsoft.com/Softlib/MSLFILES/XMS.EXE

the xms block move function which uses unreal mode is in file xm386.asm
Post 05 Nov 2009, 12:20
View user's profile Send private message Reply with quote
DOS386



Joined: 08 Dec 2006
Posts: 1903
DOS386 06 Nov 2009, 03:31
vid wrote:
CPU behaves differently. On every write to segment register, instead of using written value as selector, it shifts value left by 4, and writes it to segment base. Also, it supposedly *should* reset limit and access rights to real mode defaults (64k limit, dunno about rights).


Access Rights = FULL of course in real mode

About the limit, there are 2 issues:

1. Does the CPU reset the limit when switching to RM ? NO (otherwise unreal wouldn't work)

2. Does the CPU reset the limit when writing into DS ? I'll test ...

Quote:
But the catch is that CPU doesn't do this, and that is why unreal mode (flat real mode) works.


2. isn't necessary.

Quote:
And this is 100% working everywhere, because it is used by BIOSes, many OSes, etc.


BIOS maybe. OS no. Just some XMS hosts, some games, and FASM Smile

2 other things to reset when switching back to RM:

- CS code width to 16-bit NOT done on Intel and AMD Shocked

- CS limit to 64 KiB DONE on all CPU's

Japheth wrote:
You can look at the original Himem source. It's still available at the MS FTP server:ftp://ftp.microsoft.com/Softlib/MSLFILES/XMS.EXE the xms block move function which uses unreal mode is in file xm386.asm


Well, it is Shocked after you unpack 2 stages of PKZIP SFX Smile
Post 06 Nov 2009, 03:31
View user's profile Send private message Reply with quote
sinsi



Joined: 10 Aug 2007
Posts: 790
Location: Adelaide
sinsi 06 Nov 2009, 07:42
Quote:
Every segment register has a “visible” part and a “hidden” part. (The hidden part is
sometimes referred to as a “descriptor cache” or a “shadow register.”)

From what I understand, when you load a segment register in real mode, only
the "visible" part is loaded and the base/limit/access "hidden" part is ignored.
If you load it in protected mode, both are loaded and checked, and every memory
access using that segment uses the "hidden" part - even in real mode. Since it is cached
(to avoid going to the GDT all the time) and isn't changed by a real mode segment load
you can access the whole 4gig, even with hard-coded addresses, not just a 32-bit register.
Post 06 Nov 2009, 07:42
View user's profile Send private message Reply with quote
sinsi



Joined: 10 Aug 2007
Posts: 790
Location: Adelaide
sinsi 07 Nov 2009, 06:27
Cas wrote:
Better... if anyone dares post a sample trapping routine here, I'll appreciate it Smile

Here's the one I was thinking of - I got it years ago from the interwebs...


Description:
Download
Filename: FLAT.ASM
Filesize: 4.92 KB
Downloaded: 403 Time(s)

Post 07 Nov 2009, 06:27
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.