x86 real mode - memory addressing

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.
cotter
Posts: 2
Joined: Thu Feb 24, 2011 10:31 pm

x86 real mode - memory addressing

Post by cotter »

I have a question regarding how much memory an x86 can really address in real-address mode. The sources I have found on the internet appear to be unclear and at times contradictory. Even the Intel software developer's manual appears to be unclear.

When an x86 processor resets, it is placed in real-address mode. From the Intel 64 and IA-32 software developer's manual:
This mode implements the programming environment of the Intel 8086 processor with extensions (such as the ability to switch to protected or system management mode).
This limitation along with segmentation gives the assembly programmer the ability to only access up to 1MB of memory. The 8086 knows nothing about %eax, only %ax. However, I have found that when I write assembly code for the x86 executing in real mode, I am able to use the register %eax. More over, the following code appears to work:

Code: Select all

.code16
movl $0x9999999, %eax
movl $0x12345678, (%eax)
Afterwards, the memory at location 0x9999999 has the value 0x12345678. This behavior exists when I run my software on QEMU and real hardware (I have tested this on my own machine). This behavior appears to be un-defined in the Intel software developer's manual. That is, the manual never states explicitly what happens if I use the 32-bit registers and write values to memory that is clearly outside the supposed limits of an 8086 executing in real mode.

Certainly, my own hardware is (my CPU, that is) is a core2duo that clearly can address 2^32 and beyond. Can anyone explain why I am apparently allowed to address memory that is way outside the range of real-address memory mode.
User avatar
Karlosoft
Member
Member
Posts: 277
Joined: Thu Feb 14, 2008 10:46 am
Location: Italy
Contact:

Re: x86 real mode - memory addressing

Post by Karlosoft »

Sorry if I am writing something wrong.
The newer processors based on the 80x86 family (from 80386+) add a lot of new features in their real mode (the 32bit address for example are used also when you enable protected mode in a piece of code where you are still in real mode :)). The lenght of the operator in machine code istruction is saved like a prefix.
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: x86 real mode - memory addressing

Post by gerryg400 »

Afterwards, the memory at location 0x9999999 has the value 0x12345678.
How do you know that the memory at location 0x9999999 contains 0x12345678 ? In real mode you cannot read that location either.
If a trainstation is where trains stop, what is a workstation ?
cotter
Posts: 2
Joined: Thu Feb 24, 2011 10:31 pm

Re: x86 real mode - memory addressing

Post by cotter »

How do you know that the memory at location 0x9999999 contains 0x12345678 ? In real mode you cannot read that location either.

Code: Select all

movl $0x9999999, %eax
movl $0x12345678, (%eax)
cmpl $0x12345678, (%eax)
jz MSG
spin:jmp spin
The code at MSG calls BIOS interrupt to print some character to the screen in an infinite loop. When I ran this piece of code on my hardware, I saw the characters printing to my screen. When I run the following code:

Code: Select all

movl $0x9999999, %eax
movl $0x12345678, (%eax)
cmpl $0x123456789 (%eax)    <---- note the change in the first operand
jz MSG
spin:jmp spin
nothing prints to my screen. Furthermore, if I run the code in QEMU, I type "xp 0x9999999" and it tells me 0x12345678 is stored in that location.
tom9876543
Member
Member
Posts: 170
Joined: Wed Jul 18, 2007 5:51 am

Re: x86 real mode - memory addressing

Post by tom9876543 »

cotter wrote:I have a question regarding how much memory an x86 can really address in real-address mode. The sources I have found on the internet appear to be unclear and at times contradictory. Even the Intel software developer's manual appears to be unclear.
I am suprised that you somehow managed to research x86 real mode and write some assembly..... but you never discovered UNREAL MODE???
User avatar
Chandra
Member
Member
Posts: 487
Joined: Sat Jul 17, 2010 12:45 am

Re: x86 real mode - memory addressing

Post by Chandra »

cotter wrote:I have a question regarding how much memory an x86 can really address in real-address mode
1 Megabytes+64K. Moreover, the whole accessable memory is not available for use, given that about half of that memory is reserved for VRAM, Bios Data Area,IVT etc.
cotter wrote:The 8086 knows nothing about %eax, only %ax. However, I have found that when I write assembly code for the x86 executing in real mode, I am able to use the register %eax.
Did you run that code under 8086? Do not make mistake in assuming that 'Real Mode' is same as '8086 16 bit mode'.
Real mode means 'Real Addressing Mode'.You can use some 32 bit registers in real mode as long as you are supposed to run that code for 386+. You can't rely that to run on 8086 because 8086 uses 16 bit registers. Remember, Real mode does not necessarily mean '8086 16-bit mode'. In fact, this behaviour changes with the the newer processors in the sense that you can use 32 bit registers for general instructions(your assembler might truncate the higher bits of 32 bit registers, in some case).And as such if you employ any of those 32 bit registers, it runs on 386+ even under Real Mode.
cotter wrote:This behavior appears to be un-defined in the Intel software developer's manual. That is, the manual never states explicitly what happens if I use the 32-bit registers and write values to memory that is clearly outside the supposed limits of an 8086 executing in real mode.
You might be wrong in this case.Did you mean you accessed more than 1 Megabytes (+64K) of memory in 'Real Mode'? If this is the case, you might be employing 'Unreal Mode'.
cotter wrote:Certainly, my own hardware is (my CPU, that is) is a core2duo that clearly can address 2^32 and beyond. Can anyone explain why I am apparently allowed to address memory that is way outside the range of real-address memory mode.
You cannot address memory outside the range of real-address mode.That's impossible[AFAIK].
cotter wrote:More over, the following code appears to work:
Code:

Code: Select all

.code16
movl $0x9999999, %eax
movl $0x12345678, (%eax)
Afterwards, the memory at location 0x9999999 has the value 0x12345678.
Do you realize what your code is supposed to do? How can you say that it is accessing memory beyond 1 Megabytes?

Thank You.
Programming is not about using a language to solve a problem, it's about using logic to find a solution !
User avatar
b.zaar
Member
Member
Posts: 294
Joined: Wed May 21, 2008 4:33 am
Location: Mars MTC +6:00
Contact:

Re: x86 real mode - memory addressing

Post by b.zaar »

cotter wrote:I have a question regarding how much memory an x86 can really address in real-address mode. The sources I have found on the internet appear to be unclear and at times contradictory. Even the Intel software developer's manual appears to be unclear.

When an x86 processor resets, it is placed in real-address mode. From the Intel 64 and IA-32 software developer's manual:
This mode implements the programming environment of the Intel 8086 processor with extensions (such as the ability to switch to protected or system management mode).
This limitation along with segmentation gives the assembly programmer the ability to only access up to 1MB of memory. The 8086 knows nothing about %eax, only %ax. However, I have found that when I write assembly code for the x86 executing in real mode, I am able to use the register %eax. More over, the following code appears to work:

Code: Select all

.code16
movl $0x9999999, %eax
movl $0x12345678, (%eax)
Afterwards, the memory at location 0x9999999 has the value 0x12345678. This behavior exists when I run my software on QEMU and real hardware (I have tested this on my own machine). This behavior appears to be un-defined in the Intel software developer's manual. That is, the manual never states explicitly what happens if I use the 32-bit registers and write values to memory that is clearly outside the supposed limits of an 8086 executing in real mode.

Certainly, my own hardware is (my CPU, that is) is a core2duo that clearly can address 2^32 and beyond. Can anyone explain why I am apparently allowed to address memory that is way outside the range of real-address memory mode.
What should be happening is your address is getting truncated to 0x9999 (16 bit only addressing in real mode).

Code: Select all


.code16
movl $0x9999999, %eax
movl $0x12345678, (%eax)
movl ($0x9999), ebx

It should be reading the same value back. Just guessing I haven't tested this.
"God! Not Unix" - Richard Stallman

Website: venom Dev
OS project: venom OS
Hexadecimal Editor: hexed
shedokan
Posts: 22
Joined: Sat Jan 08, 2011 9:42 am

Re: x86 real mode - memory addressing

Post by shedokan »

b.zaar wrote: What should be happening is your address is getting truncated to 0x9999 (16 bit only addressing in real mode).

Code: Select all


.code16
movl $0x9999999, %eax
movl $0x12345678, (%eax)
movl ($0x9999), ebx

It should be reading the same value back. Just guessing I haven't tested this.
Checking that code in bochs gives a "write beyond limit error".
But you can use 32bit values and registers, store them in the memory and read them as 32bit values in real mode.

So the only think you can't do with them is access memory after 1Mib(without hacks).
Gigasoft
Member
Member
Posts: 856
Joined: Sat Nov 21, 2009 5:11 pm

Re: x86 real mode - memory addressing

Post by Gigasoft »

b.zaar wrote:What should be happening is your address is getting truncated to 0x9999 (16 bit only addressing in real mode).

Code: Select all


.code16
movl $0x9999999, %eax
movl $0x12345678, (%eax)
movl ($0x9999), ebx

It should be reading the same value back. Just guessing I haven't tested this.
No, an address is never truncated. The BIOS must have set the DS limit to 4GB without setting it back. Addressing works in the same way in protected mode and real-address mode, with the exception of the operation of segment register loads.
a5498828
Member
Member
Posts: 99
Joined: Thu Aug 12, 2010 7:25 am

Re: x86 real mode - memory addressing

Post by a5498828 »

tell me what unreal mode is really for?
why would i be unable to use prefix 0x67 to access 4 gb memory from normal real mode?

when loading pmode segments, cache is written with limit, size and base, right?
So what, what change so i can use 4gb. In real mode there are no limits/bases, why would it work?
Tosi
Member
Member
Posts: 255
Joined: Tue Jun 15, 2010 9:27 am
Location: Flyover State, United States
Contact:

Re: x86 real mode - memory addressing

Post by Tosi »

When the PC is first powered on, it is in real mode and the limit of all memory accesses is 1 MB.
If you enable the A20 line and switch to protected mode, load a real mode GDT with a base of 0 and a limit of 0xFFFFFFFF, you can access the entire address space when you drop back to real mode. That is unreal mode, and it is more of a bug or a consequence of how the descriptor caches work than anything. It is not a separate operating mode.
a5498828
Member
Member
Posts: 99
Joined: Thu Aug 12, 2010 7:25 am

Re: x86 real mode - memory addressing

Post by a5498828 »

why switch to pmode? a20 is enough to enable 32bit access.
Tosi
Member
Member
Posts: 255
Joined: Tue Jun 15, 2010 9:27 am
Location: Flyover State, United States
Contact:

Re: x86 real mode - memory addressing

Post by Tosi »

You need to be in protected mode in order to load the descriptor caches, by loading a segment register. If you load a segment register in real mode, it won't do this.
User avatar
b.zaar
Member
Member
Posts: 294
Joined: Wed May 21, 2008 4:33 am
Location: Mars MTC +6:00
Contact:

Re: x86 real mode - memory addressing

Post by b.zaar »

a5498828 wrote:tell me what unreal mode is really for?
why would i be unable to use prefix 0x67 to access 4 gb memory from normal real mode?

when loading pmode segments, cache is written with limit, size and base, right?
So what, what change so i can use 4gb. In real mode there are no limits/bases, why would it work?
The easiest way to think of real mode is like running with 16 bit selectors at ring 0. All segments (selectors) in real mode are set up with limit = 0xFFFF, Default = 0 (16 bit code) and Granularity = 0 (1 byte size), this is what you also set it back to when exiting from pmode to real mode.

Unreal mode enters pmode, creates a data selector with Base = 0, limit = 0xFFFFFFFF and Granularity = 1 (4KB size) then loads this selector into DS, ES, FS and GS and exits back to real mode. Now you can access up to 4GB memory with 32 bit addressing using the 0x67 prefix. You still need to enable the a20 line but that is separate from entering pmode. You can enable the a20 line from real mode and still not be able to access above 0x10FFEF because of the segment limits. DOS uses this trick to access the High Memory Area.
"God! Not Unix" - Richard Stallman

Website: venom Dev
OS project: venom OS
Hexadecimal Editor: hexed
a5498828
Member
Member
Posts: 99
Joined: Thu Aug 12, 2010 7:25 am

Re: x86 real mode - memory addressing

Post by a5498828 »

dont tell me what is unreal mode, tell me what i cant use 0x67 without setting cache. Real mode isnt using any protection so where the need for limit? What will happen if i use 0x67 in non unreal mode? I cant test it myself because i dont know how to interprete the result (exception wont be fired, real mode has no general protection fault thing). And emulator just say 'read/write beyond limit'. What limit, wtf. limit = protected mode. a20 is obviously enabled, otherwise i wouldnt ask.

From my understanding i will be able to access 4gb anyway, UNLESS real mode myst have loaded protected mode segments first to actually recognize 0x67 and 0x66. Dot its not the case, i can use those, just with address makeable without it (0xFFFFF being max).
Post Reply