Open main menu
Home
Random
Recent changes
Special pages
Community portal
Preferences
About Wikipedia
Disclaimers
Incubator escapee wiki
Search
User menu
Talk
Dark mode
Contributions
Create account
Log in
Editing
X86 memory segmentation
(section)
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
== Real mode == [[Image:Overlapping realmode segments.svg|thumb|right|300px|Three segments in [[real mode]] memory (click on image to enlarge). There is an overlap between segment 2 and segment 3; the bytes in the turquoise area can be used from both segment selectors. If however the program code dealing with segment 2 never uses offsets large enough to reach 0x77D0, then it can be thought of as a shorter, non-overlapping, and at most 30,672-byte segment.]] In [[real mode]] or [[Virtual 8086 mode|V86 mode]], the fundamental size of a ''segment'' is 65,536 [[byte]]s, with individual bytes being addressed using 16-bit ''offsets''. The 16-bit segment selector in the segment register is interpreted as the most significant 16 bits of a linear 20-bit address, called a segment address, of which the remaining four least significant bits are all zeros. The segment address is always added to a 16-bit offset in the instruction to yield a ''linear'' address, which is the same as [[physical address]] in this mode. For instance, the segmented address 06EFh:1234h (here the suffix "h" means [[hexadecimal]]) has a segment selector of 06EFh, representing a segment address of 06EF0h, to which the offset is added, yielding the linear address 06EF0h + 1234h = 08124h. (The leading zeros of the linear address, segmented addresses, and the segment and offset fields are shown here for clarity. They are usually omitted.) {| |- ! style=width:18em | <code> </code><code style="background:#DED">0000 0110 1110 1111</code><code>0000</code> | '''Segment''' | 16 bits, shifted 4 bits left (or multiplied by 0x10) |- ! style=width:18em | <code>+ </code><code style="background:#DDF">0001 0010 0011 0100</code> | '''Offset''' | 16 bits |- style="text-decoration:line-through" ! style=width:18em | <code> </code> | |- ! style=width:18em | <code> </code><code style="background:#FDF">0000 1000 0001 0010 0100</code> | '''Address''' | 20 bits |} Because of the way the segment address and offset are added, a single linear address can be mapped to up to 2<sup>12</sup> = 4096 distinct segment:offset pairs. For example, the linear address 08124h can have the segmented addresses 06EFh:1234h, 0812h:0004h, 0000h:8124h, etc. This could be confusing to programmers accustomed to unique addressing schemes, but it can also be used to advantage, for example when addressing multiple nested data structures. While real mode segments are ''technically'' always 64 [[Kilobyte|KB]] long, the practical effect is only that no segment can be ''longer'' than 64 KB, rather than that every segment as actually used in a program ''must'' be treated as 64 KB long β dealing with effectively smaller segments is possible: usable sizes range from 16 through 65,536 bytes, in 16-byte steps. Because there is no protection or privilege limitation in real mode, it is still entirely up to the program to coordinate and keep within the bounds of any segments. This is true both when a segment is programmatically treated as smaller than, or the full 64 KB, but it is also true that any program can always access any memory by just changing segments, since it can arbitrarily set segment selectors to change segment addresses with absolutely no supervision. Therefore, while real mode can be thought of as allowing different segment lengths, and as allowing segments to be overlapping or non-overlapping as desired, none of this is restrictively enforced by the CPU. The effective 20-bit [[address space]] of PC/XT-generation CPUs limits the [[memory address|addressable memory]] to 2<sup>20</sup> bytes, or 1,048,576 bytes (1 [[Megabyte|MB]]). This derived directly from the hardware design of the Intel 8086 (and, subsequently, the closely related 8088), which had exactly 20 [[address bus|address pins]]. (Both were packaged in 40-pin DIP packages; even with only 20 address lines, the address and data buses were multiplexed to fit all the address and data lines within the limited pin count.) {{anchor|Paragraph}}{{resize|105%|{{sidebox|above='''Example calculation:'''|text=A segment value of 0Ch (12) would give a linear address at C0h (192) in the linear address space. The address offset can then be added to this number. 0Ch:0Fh (12:15) would be C0h+0Fh=CFh (192+15=207), CFh (207) being the linear address.}}}}Each segment begins at a multiple of 16 bytes, called a ''paragraph'', from the beginning of the linear (flat) address space. That is, at 16 byte intervals. Since all segments are technically 64 KB long, this explains how overlap can occur between segments and why any location in the linear memory address space can be accessed with many segment:offset pairs. The actual location of the beginning of a segment in the linear address space can be calculated with ''segment'' Γ 16. Such address translations are carried out by the segmentation unit of the CPU. === End-of-address-space quirkiness === {{main article|A20 line}} The last segment, FFFFh (65535), begins at linear address FFFF0h (1048560), 16 bytes before the end of the 20-bit address space, and thus can access, with an offset of up to 65,536 bytes, up to 65,520 (65536β16) bytes past the end of the 20-bit address space of the 8086 or 8088 CPU. A further 4,094 next-highest 64K-segments also still cross that 1MB-threshold, but by less and less. On the 8086 and 8088 CPUs, these address accesses were wrapped around to the beginning of the address space such that 65535:16 would access address 0, and e.g. 65533:1000 would access address 952 of the linear address space. The fact that some programs written for the 8088 and 8086 relied on this quirky wrap-around as a feature led to the [[Gate A20]] compatibility issues in later CPU generations, with the [[Intel 286]] and above, where the linear address space was expanded past 20 bits. In 16-bit real mode, enabling applications to make use of multiple memory segments for a single data structure (in order to access more memory than available in any one 64K-segment) is quite complex, but was viewed as a necessary evil for all but the smallest tools (which could do with less memory). The root of the problem is that no appropriate address-arithmetic instructions suitable for flat addressing of the entire memory range are available.{{Citation needed|date=July 2011}} Flat addressing is possible by applying multiple instructions, which however leads to slower programs. The ''[[x86 memory models|memory model]]'' concept derives from the setup of the segment registers. For example, in the ''tiny model'' CS=DS=SS, that is the program's code, data, and stack are all contained within a single 64 KB segment. In the ''small'' memory model DS=SS, so both data and stack reside in the same segment; CS points to a different code segment of up to 64 KB.
Edit summary
(Briefly describe your changes)
By publishing changes, you agree to the
Terms of Use
, and you irrevocably agree to release your contribution under the
CC BY-SA 4.0 License
and the
GFDL
. You agree that a hyperlink or URL is sufficient attribution under the Creative Commons license.
Cancel
Editing help
(opens in new window)