

What about Windows 95?Īs it turns out, NDIS.VXD in Windows 95 has the exact same code for calibrating NdisStallExecution. There could well have been differences in how quickly different chipsets handled these reads, with faster access being more likely to trigger failures. As mentioned above, these would access the PIT, which means port I/O. Note that the calls to Get_System_Time make things even more interesting. A 350 MHz K6-2 would be more than five times faster on the basis on clock speed alone, but the performance differential was much bigger in practice. Given the WfW 3.11 release date (1993), the code could not have been tested on anything faster than a 66 MHz Pentium, if at all. This is exactly the kind of thing that would have been 100% solid on circa 100 MHz and slower CPUs, but when the CPU clock speed went up several times and the LOOP instruction also took fewer cycles to execute… trouble. As long as Get_System_Time does not return the same value, everything will be fine. If it takes less than one millisecond to call Get_System_Time twice and run the LOOP instruction about one million times in between, there will be a problem-because the starting and ending millisecond may be the same, causing the delta to be zero, and directly leading to a division by zero (the code is not very careful). Now, the problem with this approach is that although Get_System_Time reads the time directly using the 8254 PIT (and it could provide microsecond accuracy), it is only accurate to one millisecond. Calculate the number of LOOP iterations per millisecond.Read the current time through Get_System_Time again and calculate the time delta.Run 10000h (1,048,576) iterations of the LOOP instruction.Call the Get_System_Time VxD API in a loop until the time changes.Note that this is 32-bit protected-mode (VxD) code. The NDIS module calibrates a delay loop for the NdisStallExecution API. And that explained why the problem only showed up with the protected-mode networking stack in WfW 3.11, but didn’t actually depend on the network driver or protocols or any configuration details.Īfter a few minutes with IDA Pro, the real cause became apparent.

So I resorted to looking for the zero-dividing code sequence in Windows binaries and soon enough found the culprit: NDIS.386.
