13

While Windows 3.x operating system stuck to the 80286 platform, did applications compiled for Windows 3.x have to use 80286 instructions explicitly or be aware of the 80286 memory layout?

Or was it that as long as the source code didn't use 80286-exclusive assembly, applications could be compiled with an 8086 compiler and leave the protected-mode stuff to the OS and be transparent? If the latter was possible, how often was it the case?

1
  • 1
    The nature of protected-mode 286 programming is very similar to real-mode programming. They're both 16-bit environments and access to large memory is done with segments. Carefully written code can run in either mode.
    – RETRAC
    Commented Dec 19, 2022 at 23:52

3 Answers 3

34

Windows 3.x wasn’t “stuck to the 80286 platform”: Windows 3.0 still supported real mode on 8086 processors. The requirement for a 286 at the platform level only came with Windows 3.1.

As far as applications are concerned, the defaults for the Windows 3.0 SDK still targeted 8086 processors (using the SDK and the compiler required a 286 however). Of course developers could change this, and produce applications requiring 286s; Windows 3.0 on an 8086 was never a pleasant experience so an editor producing an application for Windows 3.0 wouldn’t lose much in the way of sales by requiring a 286 (but I don’t know whether that was obvious at the time). Such a requirement would have been mentioned on the box and was unusual in the early days of Windows 3.x at least; the point quickly became moot since any program requiring Windows 3.1 effectively required a 286 even if it didn’t use any 286 instructions itself.

The specifics of the memory model were handled by the compiler anyway; even for developers writing lower-level pointer-manipulation code, as long as they followed the rules of the Windows memory model (which wasn’t 286-specific, it applied for 8086 code too), their programs would run in any Windows mode (real, standard or enhanced).

Windows applications handled protected mode transparently; see What key factor led to the sudden commercial success of MS Windows with v3.0? for details. Note that requiring a 286 doesn’t imply anything about the use of protected mode: it can be beneficial to use the new instructions offered by the 80186 and 80286, without even switching to protected mode.

2
  • Wiki claims that the designers actually contemplated using an 8-bit shift (instead of 4-bit), in order to create a 16 MB physical address space. If 8086 were designed with 24 bit address line from the beginning, would win 3.0 no longer bother to use protected mode, or still require some form of internal/external MMU?
    – Schezuk
    Commented Dec 19, 2022 at 16:19
  • 9
    That’s a completely different question; feel free to ask a new one. But bear in mind that speculative questions aren’t appropriate here. (You may want to read up on the benefits of protected mode other than access to a larger address space.) Commented Dec 19, 2022 at 16:27
10

While Win 3.x operating system stuck to the 80286 platform,

Not really as Windows was since 2.1 available in two versions:

  • Windows/286 and
  • Windows/386

It got only unified by name with Windows 3.0. Unlike the name suggests, the difference wasn't 286 vs. 386, but real mode vs. protected mode. Protected mode was only used on 80386-class CPUs and only for Windows itself. On a 286 Windows ran the same code (and mode) as on a 8086. Applications always used (virtual) real mode.

did applications compiled to Win 3.x have to use 80286 instructions explicitly

They could use the added user-mode instructions in either mode

or be aware of the 80286 memory layout?

Not at all. Beside that it's the whole idea of Windows to hide those things, memory layout on a 286 was exactly the same as for 8086 - and in all practical means for 386, as here user tasks did run in virtual 86 mode, so no chance to 'see' anything difference in memory layout.

Or as long as the source code didn't use 80286-exclusive assembly, could applications be compiled with a 8086 compiler

Well, the default compile option for the SDK was 8086, but easy to override. Which I'm pretty sure many did to take advantage of any possible speedup.

and leave the protect-mode stuff to the OS and be transparent?

User processes were never to access any protected mode instructions.

Windows offered a standardized environment independent of hardware including CPU, a single set of calls for everything about the environment, from memory to graphics.

All Windows interfaces were 16 bit and its memory layout was 8086 alike no matter on what (sub)version.

It wasn't until Win 3.1 offered the (optional) Win32s interface that it started to support 32-bit calls.

This is not to say there were no differences. The 386 variant did offer a native EMS emulation mode, while the (2)86 used an existing HIMEM driver. While either is transparent to the user program, I do remember that it was considerably faster on a 386.

If the latter is true, how often was the case?

That's hard to guess. Since it was up to each developer to decide which CPU to target, only a look at each and every package would help here. Due to the abstraction offered by Windows, it didn't really matter. What mattered was speed and accessible memory, so lifted requirements were at that time less about the CPU itself, but the way extended/expanded memory was handled.


There seems to be a little mix-up between '286 Instructions', 'Memory Layout' and 'Protected Mode', as well as 'compiling with/without 286 features'. These are independent issues.

286 Instructions

The 286 not only brought its protected mode and the (privileged) instructions that go with it but it also extended user mode instructions with

  • Array Checking (BOUND)
  • Extended Stack Handling
    • ENTER, LEAVE, PUSHA, POPA, PUSH immediate
  • Speed Up I/O
    • INS, OUTS
  • Immediate Shifts / Rotates
  • Immediate IMUL

So applications could have a benefit from being compiled for 286 (or anything other than basic 86) without conflicting with Windows in any way. In fact, that worked already under any prior version.

5
  • A hypothesis question. If 8086 were designed with 24 bit address line from the beginning, would windows 2/3 no longer bother to use protected mode, or still require some form of external MMU?
    – Schezuk
    Commented Dec 19, 2022 at 16:12
  • 5
    That’s a completely different question; feel free to ask a new one. But bear in mind that speculative questions aren’t appropriate here. (You may want to read up on the benefits of protected mode other than access to a larger address space.) Commented Dec 19, 2022 at 16:29
  • 1
    What you wrote is not correct. Windows 3.0 did run in Protected Mode on a 286 and the Windows applications did run in Protected mode too. The mode for 286 CPUs was called standard mode, which is a mode where Windows runs in protected mode. The easiest way to recognize this is that in standard mode an application has more than 640 KiB of RAM available. And that's why the standard mode was continued in Windows 3.1, while the real mode support of Windows, which was still intended for the 8086 processors in Windows 3.0, was discontinued and removed.
    – Coder
    Commented Mar 24 at 18:13
  • @Schezuk Windows 3.0 runs on an 8086 in real mode. The reason why Protected Mode was needed on the 286 for Windows 3.x is to allow applications to have more RAM. And the fact that Windows 3.0 is still supposed to run on the 8086 has meant that the 16-bit Windows applications use cooperative multitasking and not preemptive multitasking. Because for the latter you need at least a memory protection unit in order to be able to enforce the preemptive multitasking mode. Otherwise the application will simply overwrite the kernel. The MPU was only available from the 286. The 386 even had an MMU.
    – Coder
    Commented Mar 24 at 18:23
  • @Schezuk If the 8086 had had a 24-bit wide address space, then Protected Mode would not have been necessary for Windows 3.x. The Windows programs would simply have used cooperative multitasking as usual and accessed the more ram, a 24 bit wide address space allows.
    – Coder
    Commented Mar 24 at 18:25
5

I could be mistaken—and I would love to see some examples!—but I believe that it was rare for 16-bit Windows programs to require an 80286 (although some might need an 80386). For example, Version 1.0 of Word for Windows, whose source code is now publicly available, does not appear to use 80286 instructions that I can see, nor does the documentation say it requires one. And it for example defines a 8086-compatible PushAll macro in pmword.inc rather than use the 80286 pusha instruction. My recollection of the first version of Excel that I used was that it shipped with a stripped-down “runtime” version of Windows that did not require an 80286, for users that did not own a copy of Windows. At the time, 8086-based machines such as the IBM XT were still in common use, which is why OS/2 1.0 also supported the 8086 at the time.

The privileged-mode instructions would only be used by the OS. It was in theory transparent to programs whether the 16-bit segments of memory they requested from the OS were real-mode or 80286 protected mode. Most of the remainder are actually 80186 holdovers that are not very useful to a programmer working on 16-bit Windows. The ins and outs instructions would be used by device drivers if at all, the calling convention was already defined not to use enter, leave, pusha or popa, and bound isn’t how an application programmer on Windows would check for a buffer overflow. Compilers would typically transform multiplication by an immediate constant into shifts and adds.

That means shifts and rotates by an immediate, rather than one bit or the value in cl, would have been the most useful 80286 instruction for applications. However, the benefit was small because the 80286 shift-by-immediate instructions were longer than the 8086 instructions and were microcoded to execute them as a series of one-bit shifts on that CPU. The Word for Windows source code linked above, for example, writes

shl ax,1
shl ax,1

rather than shl ax,2. However, the encoding of shl ax,1 is shorter than that of shl ax,2, so the difference in code size is only one byte. The 8086-compatible version executes in only four clock cycles on the 80286, which is faster than shl ax, 2. Three shift-by-one instructions even beat shl ax, 3. There would be no advantage unless the application needed to shift by a fairly large constant without loading it into CL.

When any applications did require an 80286, and would halt and catch fire when run on an 8086, my guess would be that shift-by-an-immediate was the reason.

6
  • 1
    "both versions need two bytes to encode," I think the 186+ shl ax, 2 needs 3 bytes to encode whereas two shl ax, 1 need 4 bytes.
    – ecm
    Commented Dec 20, 2022 at 10:43
  • Yup, shl ax, 2 is 0xC1E002, shl ax, 1 is 0xD1E0 (or 0xC1E001 but that’s not interesting). Commented Dec 20, 2022 at 13:37
  • @ecm Thanks, corrected.
    – Davislor
    Commented Dec 20, 2022 at 20:09
  • 2
    "the encoding of shl ax, 2 needs more bytes to encode than shl ax, 1 twice" ??? The encoding of a shl ax, 2 needs less than shl ax, 1 twice. You didn't fix the error at all.
    – ecm
    Commented Dec 20, 2022 at 21:20
  • 2
    and would halt and catch fire when run on an 8086, - true except for the halting : 8086 doesn't have a #UD illegal-instruction fault; every byte sequence decodes as something. Just not the same thing as on later CPUs that define those sequences. e.g. I've read that on early steppings of 8086, 0F was pop cs and actually executed as such. (On later CPUs, it's the "escape" byte for 2-byte opcodes.) Commented Dec 21, 2022 at 11:50

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .