A history of GlobalLock, part 2: Selectors

With the advent of the 80286, Windows could take advantage of that processor's "protected mode". processor. There was still no virtual memory, but you did have memory protection. Global handles turned into "descriptors", more commonly known as "selectors".

Architectural note: The 80286 did have support for both a "local descriptor table" and a "global descriptor table", thereby making it possible to have each process run in something vaguely approximating a separate address space, but doing so would have broken Windows 1.0 compatibility, where all memory was global.

Addresses on the 80286 in protected mode consisted of a selector and an offset rather than a segment and an offset. This may seem like a trivial change, but it actually is important because a selector acts like a handle table in hardware.

When you created a selector, you specified a whole bunch of attributes, such as whether it was a code selector or a data selector, whether it was present or discarded, and where in memory it resided. (Still no virtual memory, so all memory is physical.)

GlobalAlloc() now returned a selector. If you wanted to, you could just use it directly as the selector part of an address. When you loaded a selector, the CPU checked whether the selector was present, discarded, or invalid.

  • If present, then everything was fine.
  • If discarded, a "not present" exception was raised. (Wow, we have exceptions now!) The memory manager trapped this exception and did whatever was necessary to make the selector present. This meant allocating the memory (possibly compacting and discarding to make room for it), and if it was a code selector, loading the code back off the disk and fixing it up.
  • If invalid, an Unrecoverable Application Error was raised. This is the infamous "UAE".

Since memory accesses were now automatically routed through the descriptor table by the hardware, it meant that memory could be moved around with relative impunity. All existing pointers would remain valid since the selector remains the same; all that changes is the internal bookkeeping in the descriptor table that specified which section of memory the descriptor referred to.

For compatibility with Windows 1.0, GlobalAlloc() continued to emulate all the moveability rules as before. It's just that the numeric value of the selector never really changed any more. (And please let's just agree to disagree on whether backwards compatibility is a good thing or not.)

Next time, transitioning to Win32.

Comments (15)
  1. Matt says:

    Surely Windows 1.0 was the one OS that MS could have afforded to break compatibility with!

  2. mschaef says:

    This 286 protected mode stuff was first introduced in Windows 3.0 standard mode, no?

  3. Anonymous Coward says:

    I wrote most of my assignments at university using Write on Windows 286!

    The thing I don’t remember is if Windows 286 had virtual memory of any sort. From the above scheme it was possible.

  4. mschaef says:

    "The thing I don’t remember is if Windows 286 had virtual memory of any sort. From the above scheme it was possible. "

    Part of the reason I asked my question was that I thought I remembered that Windows/286 didn’t do anything 286 specific other than unmask the A20 line and allocate memory in the 1024-1088K range. Otherwise, it was plain old real mode.

    I’m not 100% sure about this, however.

  5. Nicholas Allen says:

    286 wouldn’t have had virtual memory. You need paging so that you can give applications a logical view of memory rather than a physical view. That didn’t happen until the 386.

  6. Tom says:


    Couldn’t Windows 286 use more than 1MB? I think it could allocate memory upto the 16MB limit (the segment base in the descriptor was 24-bit) on the processor.

  7. Ben Hutchings says:

    Nicholas: Selectors provide that virtualisation. I’d say swapping of entire segments is a kind of virtual memory, even though it’s rather less useful than paged virtual memory.

  8. Michael J. says:

    i286 allowed up to 16MB of RAM, and Windows could use it. I remember running Win3.0 in Standard Mode on my 286. One needed at least 1MB to run Windows in Standard Mode. We had got several 286 machines with 1MB onboard and with 1MB expansion card in each. The card was taking a full-length full-height 16-bit ISA slot. The expansion card allowed to set the starting memory address which it served, so I pulled one card from a machine which was intended for DOS tasks only, and put it into my machine, thus I got two huuuuge cards inside and a whopping 3MB memory. Windows was able to use all of it. As always, Windows perfomance did depend mostly of RAM size. It was barely usable with 1MB, but really flied (err, like a DC10, not like F-16) with 2MB or more. Word 2.0 was a very nice wordprocessor, but I still favored Word 6.0 for DOS for its speed and small size.

  9. ATZ Man says:

    There are 13 bits available in a selector for indexing the LDT or GDT. The processor was capable of combining this with all or almost all of the segment base bits to access more than 16MB overall. However I never heard of an OS that tried to do that. OSs generally just worked with the offset as an offset into a uniform memory space.

    In a Windows/286 system, there would have been a lot of junk competing for the 0-640K region and there would be ISA I/O boards mapped in between 640K and 1MB.

    I think Windows/286 could spill stuff to the hard drive in temporary files or use an XMS banking scheme to use more RAM than 16MB. Most people concerned about performance in those days would have a RAM drive in XMS.

    The article on GlobalLock in Windows/386 is going to be short :)

  10. Mike Swaim says:

    I had a ‘286 with 6 MB of memory. (6 was on an ISA card using SIMMs liberated from old Sparkstations.) Windows was MUCH faster with my temp directory on a 2 MB RAMDisk.

  11. Sven G. Ali says:

    If I recall correctly, the 286 supported segmented (rather than paged) virtual memory. The segment descriptor tables provided the address translation layer that was the key to virtual memory. It was less efficient than paging, but only because segments were variable in size and therefore more difficult to manage. Everything else was there – segmentation faults for swapping, protection bits, etc.

    The address space consisted of a maximum of 8192 GDT and 8192 LDT segments, for a theoretical maximum of 1GB (16K segments x 64KB). The processor was of course limited to 16MB of physical RAM.

    The 286’s Protected mode also provided a bewildering array of other hardware features that supported the implementation of a fully multithreaded, memory-protected OS (e.g., hardware support for thread switching). Unfortunately I think OS/2 1.x was the only OS that took advantage of them all.

    The thing that most impressed me about early Windows versions is that MS invented a programming model that abstracted away the tremendous differences between Real and Protected modes, allowing Windows apps to run on both without recompilation. I still think that was some feat. Raymond, did the 286 exist when you guys were working on Windows 1.x?

  12. ATZ Man says:


    One of the model numbers was "introduced" in 1982 and was manufactured in 1984.

  13. "(And please let’s just agree to disagree on whether backwards compatibility is a good thing or not.)"

    Backwards compatiblity is a good thing…but surely you are not still trying to be compatible with Windows 1.0!!!


  14. beuges says:

    WinXP has to be compatible with Win2k, which has to be compatible with NT and Me, which have to be compatible with 98, which has to be compatible with 95, which has to be compatible with 3.1, which has to be compatible with 3.0, which has to be compatible with 2, which had to be compatible with 1.0.

    Sure now its easy to say "But no-one uses Windows 1.0 any more, you can break compatibility with that", but theres a chain that’s been created now… breaking windows 1.0 compatibility will break some Win 3.1 or 95 or XP program that was written using functionality that hasn’t changed since Windows 1.

    Altho the moveability rules for GlobalAlloc are now pretty redundant, there’s some program somewhere that’s passing in those parameters and expecting things to work as they used to.

  15. And just for kicks, the apps (calc, clock etc.) that came with Windows 2.0 still run under Windows XP…. Haven’t tried SP2.

    But of course that compatibility isn’t perfect, I have a copy of "Windows Draw 4.0" (can’t remember who makes that), but they did some crazy owner drawing of the File>Open dialog, but they based their drawing on the coordinates on the dialogs in Windows 95 and NT4, so since Windows 98 and 2000 changed that dialog quite a lot this program hasn’t allowed us to open or save files. But that is the software companies fault, not Microsofts.

Comments are closed.

Skip to main content