In article <10d3ms6$2q7cs$
1@dont-email.me>,
Peter Flass <
Peter@Iron-Spring.com> wrote:
On 10/19/25 14:37, Lawrence D?Oliveiro wrote:
Intel finally added a linear address space to its first 32-bit x86
processor in 1985
<https://www.tomshardware.com/tech-industry/semiconductors/intel-386-at-40>. >> This was the point where all the old segmentation crap could start
going away, though it took a while for backward-compatibility reasons.
This was the CPU that was in Linus Torvald?s PC at University -- the
one he developed the first version of Linux on.
This was also the CPU that allowed Microsoft to create a version of
Windows that people found genuinely useful: its ?virtual-86? mode
allowed users to run multiple DOS programs at once, without their
having to be modified in any way to support multitasking, and Windows
2.1 (aka ?Windows/386?) took full advantage of this.
It was all handled by the protected-mode hardware offering a virtual
?real-mode? environment for software that knew nothing about protected
mode--in fact, it could offer multiple such environments running
concurrently, isolated from each other so a crash in one would not
affect the rest. Finally: a reason to buy Microsoft Windows, without
having to wait for developers to come out with actual software that
took advantage of Windows!
I always thought they screwed up the naming. "Segmented mode" and
"linear mode", or something else for the second. To me "real" and >"protected" made no sense.
The 80286 introduced the notion of privilege levels and
protection rings, and applied them to segments; hence, the
notion of "protection": in order to access a given segment, the
processor had to be operating in a correctly privilged ring.
The protection level required was described in a descriptor for
the given segment, which also gave its base and bound; such
descriptors were listed in a table, the base address of which
was loaded into a CPU register. Segments are "selected" by
moving their index into a segment register; for most
instructions, which segment is used is implicit in the
instruction itself, though "long" (or "far") jumps can be made
to an explicit segment.
One enables the whole mechanism by setting a bit in a CPU
control register (bit 0 of the "Machine Status Word" on the 286;
CR0[PE] on the 80386 and pretty much everywhere after), and that
mode was called "protected virtual address mode", or more
commonly, "Protected Mode", since the memory protection
mechanism is enabled and used.
What we refer to as "Real Mode" was called "Real Address Mode"
by Intel, and that's the address model used on the 8086 and 8088
(and the 80186). Real Address Mode still uses segmentation, but
it's the anemic variety of the 8086: the contents of a segment
register are left-shifted 4 bits and added to a 16 offset to
form a 20-bit "linear" address; the 20 bit address is what's put
onto the address bus in a memory access cycle (note: the same
bus is also used for programmed IO, but the PIO instructions
cause another line to be asserted that feeds into the external
chip select logic and activates IO functions, as opposed to
memory functions).
Why did they call that "real"? I suspect the 8086/88/186/188
mechanism was reconned and called that because "real" is the
opposite of "virtual", and 80286 segmentation was clearly meant
to address a virtual memory capability to the architecture. You
had to explicitly turn on virtual memory, and if you didn't do
that, you were using Real memory. Or something like that.
Note that with a 16-bit segment number and 16-bit offset within
the segment, one can construct an address that overflows a
20-bit value: e.g., segment base 0xffff, and offset 0xffff:
0xffff<<4+0xffff = 0xffff0+0xffff = 0x10ffef, which sets the
21st address bit. On the 8086/8088 etc, this bit is carried out
of existence and lost; there is no adress line to which it can
be directed, so the resulting linear address is simply 0xffef.
Programmers, being programmers, took advantage of this: given a
segment up near the top of memory, they could cause it to wrap
around and write to the "Interrupt Vector Table", which set
interrupt handlers, and started at linear address 0. But the
80286 widened the address bus to 24 bits, allowing programs to
address a full 16MiB address space (albeit in units of max 64KiB
segments).
To retain compability with DOS and programs written for the 8086
on the IBM PC platform and clones, the infamous "A20" gate was
introduced: 16 bit programs weren't in any real danger of
generating addresses that set any bits beyond the 21st, so a
logic gate was added to the IBM PC AT that interposed between
the A20 line coming from the CPU and the external address bus.
When disabled, the gate held the the 21st address line low
regardless of what the CPU thought it should be; this let 8086
programs work unmodified on a 286. Systems software that wanted
to take advantage of the larger address space had to manually
enable the gate. Of course, you don't need much more than an
AND gate here: one input is connected to the CPU's A20 line, the
other to a latch driven high when the gate is enabled, and low
when not. An otherwise-unused flip-flop on the i8042 keyboard
controller was repurposed for this; the 80486, however, had to
introduce a special line for this to accommodate backwards
compatibility in its physically addressed on-chip cache.
In the 80386, segmentation was again retained, but segment
descriptors were modified with a "granularity" bit that
effectively allowed them to cover a flat 32-bit address space.
Paging was also added, and a surprisingly reasonable page table
format added; the '386 was designed to compete in the Unix
workstation market. Segmentation combines with paging in the
creation of linear addresses in the physical address space: the
CPU applies whatever transformations segmentation demands to
derive an address that is then resolved in the paged virtual
address space to create a linear physical address. Note however
that the ring-based protection mechanism is weakened in this
model: while the 80286 introduced four protection levels, the
page x86 page table format only makes a distinctin between 2:
you're either in user (ring != 0) or in kernel (ring == 0) mode,
x86-64 weakens this even further, by effectively ignoring
segment base and bounds when operating in 64-bit "long" mode.
- Dan C.
--- PyGate Linux v1.5
* Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)