9

In the Intel 64 & IA-32 architecutures manual vol 3A, Chapter 9 Processor Management and Initialization, I found the the following:

Compatibility mode execution is selected on a code-segment basis. This mode allows legacy applications to coexist with 64-bit applications running in 64-bit mode. An operating system running in IA-32e mode can execute existing 16-bit and 32-bit applications by clearing their code-segment descriptor's CS.L bit to 0.

Does this mean that legacy 16-bit & 32-bit application can coexist with 64-bit application on an operating system running in IA-32e mode.

But as I know, legacy 16-bit code is generally not supported by 64-bit operating system. If it is supported, how can I startup a 16-bit application?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Gary Yin
  • 525
  • 6
  • 17
  • Legacy *protected mode* 16-bit programs. Exceedingly rare, operating systems just don't bother. Virtual 8086 mode isn't supported so DOS programs require an emulator. – Hans Passant Feb 15 '14 at 15:42
  • related: https://superuser.com/questions/140953/why-cant-a-64-bit-os-run-a-16-bit-application , related for Linux: https://stackoverflow.com/questions/7829058/running-16-bit-code-on-32-bit-linux – Ciro Santilli OurBigBook.com May 07 '18 at 09:26

3 Answers3

10

16-bit DOS apps can't run under 64-bit Windows, because virtual-8086 mode isn't available in long mode

However 16-bit protected mode is still available, so technically it's possible to run 16-bit Windows 3.x apps. That's how Wine runs 16-bit Windows apps in 64-bit Linux. Unfortunately 64-bit Windows doesn't have the same capability, although the reason is not because 64-bit mode cannot run 16-bit instructions but because the significant part has been increased.

The primary reason is that handles have 32 significant bits on 64-bit Windows. Therefore, handles cannot be truncated and passed to 16-bit applications without loss of data.

https://learn.microsoft.com/en-us/windows/win32/winprog64/running-32-bit-applications

So if you want to run 16-bit apps on 64-bit Windows you have to use a virtual machine

For more detailed information please read Peter Cordes' answer

See also Can a 64-bit computer (x86) run a 16-bit OS natively, without emulation?

Community
  • 1
  • 1
phuclv
  • 37,963
  • 15
  • 156
  • 475
  • You know, I have been troubled by this issue for a long time. Now I finally have a decent answer. I take it that Wine on linux amd64 builds has similar issues? – Olorin Mar 30 '15 at 22:48
  • @Olorin Wine on 64-bit Linux can run 16-bit Windows apps without problem because it doesn't suffer from the 32-bit handle issue – phuclv Jan 24 '20 at 05:34
  • If only MicroSoft would go open-source, then someone would definitely come up with a custom 16-bit VDM ;-) – Olorin Jan 16 '23 at 17:56
  • @Olorin people already did that in Wine and ReactOS. There's nothing tricky about it – phuclv Jan 17 '23 at 02:06
3

Under a 64-bit kernel, 16-bit protected-mode user-space is available, but virtual-8086 mode isn't.

Most 16-bit software is written for DOS, and expects to run in real mode. vm86 (virtual-8086) mode is basically hardware virtualization for real mode, allowing the guest to use cli / sti without affecting the real IF bit in EFLAGS for example.

In 16-bit protected mode, cli would only work if the IO privilege level was 0 (like ring 0), and it would disable interrupts on that actual CPU core, not just inside the 16-bit emulated environment. Thus it's not useful for running 16-bit DOS programs under a modern OS.

So yes, you can run 16-bit user-space code under a 64-bit kernel, but only in 16-bit protected mode which nobody ever uses (AFAIK). I don't think Linux natively supports 16-bit processes, although perhaps you could create a custom 16-bit code segment with the modify_ldt system call, and jmp far to it.


It might have been possible to build a software-virtualization system that used 16-bit protected mode to run 16-bit DOS guests, trapping to the kernel/hypervisor when the guest ran instructions like cli. @Lưu Vĩnh Phúc's answer is one reason that MS didn't try to do that.

Software-virtualization of x86 is non-trivial, though, because some instructions that you need to emulate (like pushf) don't actually trap. The guest could notice (or break because of) the Interrupts-enabled flag (IF) in the pushf result not matching a cli it just ran.


Even the slowest x86-64 CPUs are plenty fast enough to run software like DOSBOX that fully emulates an x86 PC with directly-accessible old hardware, so there wasn't much demand for being able to run 16-bit code natively, or much demand for running it in a way that looked "native", i.e. able to launch other programs under the main OS instead of just inside the emulated environment.

Apparently there was a Linux patch (last updated in 2008) to run vm86 under a 64-bit kernel, maybe by switching the kernel to protected mode temporarily? Or by just running software emulation.


It's possible for a 64-bit kernel to switch back to legacy mode, making it possible to use vm86 mode.

Some kernels in real life actually do run some/most of the kernel in 32-bit mode, perhaps only switching into long mode when 64-bit user-space needs to run, or to read/write RAM that can't be mapped into the limited 32-bit virtual address space.

I think I've read that MacOS did / does this, perhaps to support 32-bit binary kernel drivers.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • 1
    Technically speaking unless you have a processor that supports Virtual Mode Extensions (VME) and the OS enables the VME bit in CR4 there are no virtual interrupt flag support at the processor level. VME was new for the 486 SL processors and the Pentiums. First generation Ryzen processors support VME but a serious bug cripples its usage and you have to fall back to non-VME v8086. – Michael Petch Jan 24 '20 at 14:20
  • **Without VME** if you run with in v8086 mode with IOPL=3 the CLI and STI instructions will modify the real IF flag without trapping. Such code is problematic because a ring 3 program could disable interrupts with CLI and sit in an infinite loop that can't be interrupted. With IOPL=0 CLI and STI will trap and you have to simulate the interrupt flag (create a virtual one) but this can cause incompatibilities with real mode code that check the IF flag directly. VME was designed to overcome many of these shortcomings in v8086 mode by introducing a hardware virtual interrupt flag in EFLAGS. – Michael Petch Jan 24 '20 at 14:21
  • 2
    As for that old Linux patch, it creates a kernel module and virtual device that places the processor into v8086 mode (legacy mode) instead of long mode. – Michael Petch Jan 24 '20 at 14:36
1

32 Bit application is supported by 64 bit architectire, so they can coexist, regarding 16 Bit application you need some tools to emulate addresing space shuch as dosbox on windows

Saddam Abu Ghaida
  • 6,381
  • 2
  • 22
  • 29