The other day I investigated a report that a C runtime library modification causes programs to hang on a classic IBM 5150 PC with no math coprocessor. The runtime originally contained two separate routines, one to detect the presence of an FPU and the other to detect the FPU type.
Someone noticed that the code in the two routines looked really similar and decided to merge them. The reworked code runs just fine on 386 and later processors, with or without FPU (I’m unsure of its status on 286 machines). But it does not work on an FPU-less 8088; it causes the system to hang.
The old code looked like this:
push BP ; save BP mov BP,SP ; get access to stack sub AX,AX ; start with a preset value push AX ; allocate space for ctrl word fninit ; initialize math coprocessor fnstcw word ptr -2H[bp] ; store cntrl word in memory pop AX ; get control word mov AL,AH ; get upper byte pop BP ; restore BP
If the routine returned the value 3, a math coprocessor was found, otherwise there wasn’t one.
The new code looks like this:
push BP ; save BP mov BP,SP ; get access to stack sub AX,AX push AX ; allocate space for status word finit ; use default infinity mode fstcw word ptr [BP-2] ; save control word fwait pop AX mov AL,0 cmp AH,3 jnz nox87 ...
It’s almost the same, but hangs on an 8088 without an 8087. Why does that happen?
Continue reading