The other day I discovered that 32-bit FreeBSD 11.2 has strange trouble running in an emulated environment. Utilities like ping or top would just hang when trying to print floating-point numbers through printf(). The dtoa() library routine was getting stuck in an endless loop (FreeBSD has excellent support for debugging the binaries shipped with the OS, so finding out where things were going wrong was unexpectedly easy).
Closer inspection identified the following instruction sequence:
This code relies on “undefined” behavior. The FUCOM instruction compares two floating-point values and sets the FPU condition code bits. The FNSTSW instruction stores the bits into the AX register, where they can be tested directly, or the SAHF instruction first copies them into the flags register where the bits can be conveniently tested by conditional jump instructions.
The problem is the FSTP instruction in between. According to Intel and AMD documentation, the FSTP instruction leaves the FPU condition codes in undefined state. So the FreeBSD library is testing undefined bits… but it just happens to work on all commonly available CPUs, in a very predictable and completely deterministic manner, because the FSTP instruction in reality leaves the condition bits alone. What is going on?
The 8086/8088 is a 16-bit processor and offsets within a 64K segment always wrap around. If a one-byte instruction at offset FFFFh is executed on an 8086, execution will continue at offset 0. This is simply a consequence of the Instruction Pointer (IP) being a 16-bit register.
Funny things happen when an access crosses a segment boundary. On an 8086, it will also wrap around; accessing a word at offset FFFFh will access one byte at offset FFFFh and one byte at offset 0 in a segment. Again, that is a consequence of 16-bit address calculations.
The 80286 got a lot smarter about this. Segment protection prevents accesses that wrap around the end of a segment, for both data and instructions. The 80386 continued using the same logic.
The 286 and 386 support one special case, stack wraparound. When the 16-bit Stack Pointer (SP) is zero, pushing (say) a word on the stack will wrap around and the new SP will be FFFEh. This feature was required for 8086 compatibility, because a full size 64K stack needs to start with SP=0 (the pushes and pops must be aligned for the wraparound to occur; unaligned accesses will cause protection faults).
Does the instruction pointer also wrap around in a way similar to the stack segment?
Everyone knows that the IBM PC established 512-byte sectors on floppies and hard disks as the standard, which survived for several decades until the advent of “native” 4K-sector drives.
Of course what “everyone knows” is not necessarily the whole story.
PC Floppy Sector Sizes
The original 1981 IBM PC Technical Reference says: The [IBM PC floppy] drives are soft sectored, single sided, with 40 tracks. They are Modified Frequency Modulation (MFM) coded in 512 byte sectors, giving a formatted capacity of 163,840 bytes per drive.
But that was never really true; while PC DOS 1.0 indeed used 8 sectors per track, resulting in 163,840 bytes (512 × 8 × 40 bytes) on a floppy disk, PC DOS 2.0 supported 9 sectors per track on the same hardware, with increased 184,320 bytes disk capacity. This was possible in large part because the BIOS in the IBM PC was fairly flexible when it came to floppy disk formats.
(This is a guest post by Antoni Sawicki aka Tenox)
Project Monterey was an attempt to unify the fragmented Unix market of the 90s in to a single, cross vendor Unix OS that would run on the upcoming Intel Itanium (and others) CPU. The main collaborators were: IBM, who brought its AIX, SCO brought UnixWare, HP was supposed to bring parts of HP-UX and SequentDYNIX/ptx. Ironically the project shared fate of the Itanium CPU—it totally failed. In the end Linux took spot of the “single Unix OS”. IBM donated AIX pieces to Linux instead and the main legacy of Project Monterey was the famous SCO vs IBM lawsuit.
IBM did however produce AIX version for the Itanium architecture! According to Wikipedia, some 30+ licenses were sold in 2001-2002. For years a dedicated group of individuals was trying to locate a copy of the legendary OS. It seemed that the OS was lost forever…
This is a guest post written by Marko Štamcar from the Slovenian Computer Museum in Ljubljana. Additional context and commentary from the OS/2 Museum can be found at the end of the article.
Slovenia being a tiny country with a population of just 2 million, IBM OS/2 Warp 4 was one of the few non-Microsoft operating systems to be localized to Slovenian in the mid-90s and a big deal for the local IT community back then. But nearly 3 decades later, when OS/2 disappeared from the last ATMs in the country, the even rarer Slovenian version was as good as completely gone. Or was it?
Cue the Slovenian Computer Museum and our software heritage/conservancy activities. I have been part of the museum for the last 5 years and am the head of the laboratory (responsible for getting old machines to work for them to be shown off) and vice president of our non-profit organization. Our museum was founded in 2004 as part of the local hackerspace Kiberpipa/Cyberpipe but has since outgrown its humble beginnings and is now located in a dedicated space with 700 square meters of useful room on three levels dedicated to museum storage, exhibition and event space, and two classrooms. (More info on the museum’s website.)
A few days ago I spent far too much time debugging a largish piece of 16-bit Windows code written in assembler. I found a scenario where (fortunately fairly reproducibly) Windows crashed because the internal state of a DLL got corrupted.
I could see that the state made no sense and a supposedly small rectangle was suddenly tens of thousands of pixels large, causing segment overruns when it was copied. The internal state of the DLL was corrupted, and it very much looked like a buffer overflow.
I added size checks to make sure nearby buffers weren’t being overwritten, but the checks never fired. Or rather they only fired when the state was already corrupted.
Then I tried reshuffling the data so that the buffer which I suspected of overflowing was at the very end of the data segment, hoping that it would cause a protection fault when the buffer overrun happened. But the fault never happened, and the state was still getting corrupted.
The code was developed on a Windows 10 host system. For extra credit, I attempted to build the minidriver on Windows 9x. Ideally with source code control… but is that even possible?
I could not find any clear information on whether Mercurial ever worked on Windows 9x. After a longish software archaeology session, I concluded that it did, at least somewhat. Here’s the proof:
I used a Mercurial 1.1.2 installer downloaded from here. As far as I can tell, none of the downloads from the official site (Mercurial 1.4 and later) work on Win9x—Mercurial installs without complaints, but fails to do anything useful, possibly because of Python incompatibility with Windows 9x.
But Mercurial 1.1.2 works, least on Windows 98 SE and Windows Me. It fails to clone over HTTP on plain Windows 95 because the Python socket module won’t load. There may be a way to upgrade the Windows 95 socket support but that is of limited interest to me given that Windows 98 SE works without tweaking. I have not tried to figure out if and how well other Mercurial versions work, since 1.1.2 did the job I needed.
With the source code on a Windows 98 machine, it’s no problem building it with the Open Watcom C/C++ 1.9 compiler, it is just a question of running wmake. Happy hacking!
A kind reader from a land formerly beyond the Iron Curtain recently supplied the OS/2 Museum with a curious word processor that calls itself WordSet. The files unfortunately lost their original timestamps quite some time ago, but it is apparent that this editor was released in the late 1980s, with copyright messages in different files referring to 1986 and 1988.
The editor runs on DOS, but there appears to have been a CP/M variant available as well, as evidenced by this manual (photo from an auction):
When the DOS version of WordSet (WS.COM) is started, the user is greeted by a screen that may look more than a little familiar:
It is not difficult to see that WordSet is really WordStar, superficially renamed and with user visible text translated to Czech.
The OS/2 Museum has made available the first version of a display driver disk for Windows 9x running on VirtualBox. The driver uses a linear framebuffer and supports 8/16/24/32bpp modes with resolutions up to 1920×1200 pixels (see more below). The driver is not accelerated but tends to be very speedy on modern hardware.
I’d like to say that it was easy to adapt the existing Windows NT video miniport driver for Windows 9x… but of course it wasn’t. The Windows 9x display driver model is completely different and has nothing in common with NT. The Windows 9x display driver has much more in common with Windows 3.1 (and 3.0 and 2.x) drivers, and it has clearly directly evolved from those older drivers.
So what makes it a “minidriver”? A Windows 2.x/3.x display driver has to implement a very significant chunk of GDI. Bit blits, lines, text output. There is a lot of cases to handle and a great deal of complexity. To give some sense of the complexity, the Windows 3.1 DDK sample driver for Video 7 cards is about 1.6 MB (circa 60,000 lines) of assembler source code. And that’s just for 8bpp displays.