I recall this hack as being written by Bob Smith, who did the old DOS-era memory manager called 386MAX (or "386 to the Max"). It wasn't part of the product, it was a little utility program he whipped up and posted somewhere. However, on the web the only reference to this technique I can find is a DDJ Undocumented Corner column from November 1996 by Robert Collins.
The Problem
Prior to Intel introducing the CPUID instruction, it was difficult to check the exact type and revision levels of the CPU on your system. It turns out that in most versions of the 386 and later, there actually was a CPU ID, but it was only visible at one specific time: right after the processor was reset in the EDX register. (It was assumed that the computer's BIOS would be the only software legitimately interested in this).
Problem: how can a normal program retrieve this register value if we are not the BIOS?
Background Material
This hack relied on six distinct peculiarities of IBM PC compatible computers. They were as follows:
- Starting with the IBM AT and later, there is a way to independently disable the A20 address line on the bus.
- Most computers do not have RAM installed in very high memory addresses just below the BIOS ROM.
- Most IBM PC bus computers return 0xFF when you read a memory location that has no memory installed there.
- 0xFF 0xFF 0xFF etc is an illegal opcode on Intel CPUs.
- If you install an exception handler in memory, it will survive a soft reboot on most CPUs of this era (386 through 486).
- Upon soft or hard reset, Intel processors jump to an address which is at the top of addressable memory, minus 16 bytes, which is why the BIOS ROM is placed there.
The program combined knowledge of all these pieces of trivia to achieve the goal.
The Hack
The result was a DOS command line program, that did the following:
- Installed an illegal opcode exception handler
- Turned off the A20 address line on the bus
- Soft-rebooted the CPU (I think this was through a BIOS call)
When the soft reboot occurred, the processor would try to jump to the top of memory minus 16 bytes, which is where the ROM startup code is located. However, since A20 was off, it would actually jump to top of memory minus 16 bytes minus one megabyte. On most PCs there is no RAM there. So it would fetch a series of 0xFF bytes from this non-existent RAM, and try to execute it. This would create an illegal opcode exception.
His exception handler would then pluck out the value of EDX (the CPUID) and stash it somewhere he could find it. It would then clean up the mess (turn A20 back on, flip back from protected mode to real mode for DOS) and return control to the original code.
When it worked, it was genius to behold. Voila, here was a simple command-line DOS program that would give you the CPUID value.
Of course, there were inevitably PCs out there which were "not quite compatible" which would crash horribly when you ran this. Ah well.