Intel x86 Assembly Language & Microarchitecture Real Mode


When Intel designed the original x86, the 8086 (and 8088 derivative), they included Segmentation to allow the 16-bit processor to access more than 16 bits worth of address. They did this by making the 16-bit addresses be relative to a given 16-bit Segment Register, of which they defined four: Code Segment (CS), Data Segment (DS), Extra Segment (ES) and Stack Segment (SS).

Most instructions implied which Segment Register to use: instructions were fecthed from the Code Segment, PUSH and POP implied the Stack Segment, and simple data references implied the Data Segment - although this could be overridden to access memory in any of the other Segments.

The implementation was simple: for every memory access, the CPU would take the implied (or explicit) Segment Register, shift it four places to the left, then add in the indicated address:

Segment | 16-bit value      | 0 0 0 0 |
Address | 0 0 0 0 | 16-bit value      |
Result  |  20-bit memory address      |

This allowed for various techniques:

  • Allowing Code, Data and Stack to all be mutually accessable (CS, DS and SS all had the same value);
  • Keeping Code, Data and Stack completely separate from each other (CS, DS and SS all 4K (or more) separate from each other - remember it gets multiplied by 16, so that's 64K).

It also allowed bizarre overlaps and all sorts of weird things!

When the 80286 was invented, it supported this legacy mode (now called "Real Mode"), but added a new mode called "Protected Mode" (q.v.).

The important things to notice is that in Real Mode:

  • Any memory address was accessible, simply by putting the correct value inside a Segment Register and accessing the 16-bit address;
  • The extent of "protection" was to allow the programmer to separate different areas of memory for different purposes, and make it harder to accidentally write to the wrong data - while still making it possible to do so.

In other words... not very protected at all!