Inside Windows 3

18 points by calvin


drs

Matt Pietrek has a book (Windows Internals) that explored Windows 3.1 internals based off of disassembly: http://www.bitsavers.org/pdf/microsoft/windows_3.1/Pietrek_-_Windows_Internals_1993.pdf

I have a hard copy of this book and I can read 16 bit x86 assembly but it’s still way over my head.

david_chisnall

Win16 DLLs are quite interesting. Most platforms’ shared libraries are position-independent code, but this was hard on the 8086. The 8086 had no way of doing PC-relative addressing. To get the PC, you did a call instruction one instruction forward and then popped the spilled return address from the stack. That then consumed a register, and there weren’t many available (four main registers, four index registers including the stack pointer, and constraints for a number of instructions on which registers they could use). This meant that position-independent code was much slower than normal code (and nothing was fast on these machines).

Instead, Windows 3.0 made DLLs position dependent and statically relocated them. Each DLL had a base address where it would be loaded and the system included a constraint solver that would look at every Windows .EXE, find the DLLs it loaded, and work out a layout that allowed every DLL to be loaded at non-overlapping addresses.

As I recall, Win32 did the same thing, but had two advantages. First, they had a much bigger address space, so mapping each DLL at a unique location was much easier. Second, as I recall, Windows 95 and NT had a fallback mechanism where they could load a DLL twice and relocate it differently, so if the constraint solver failed to find a solution they could still run programs.

It’s interesting that 64-bit x86 moved towards making RIP-relative addressing cheaper, when a 64-bit (or 48-bit) address space pretty much guarantees that any system would be able to do the win16 approach there. Since then, there’s been more work on code signing and immutable images, which make install-time relocation less desirable, so in retrospect it was probably the right call.