[net.micro] FORTRAN80 and MACRO80 bugs

piner@pur-phy.UUCP (Richard Piner) (02/23/84)

  I have found two bugs in the Microsoft FORTRAN80 and MACRO80
system sold by Radio Shack. I assume they are in the CP/M
version as well. I will detail these bugs, because they have
caused me a great deal of trouble in tracking them down. It
takes a long time to find things like this, since compiler
bugs are not what you think of first. I hope this may save
some of you some time in the future. The first bug has to
do with the logical IF statement. Here is a sample subroutine.

	SUBROUTINE BUG2
	LOGICAL CHAR  (,STBKEY)
  10	IF(.NOT.STBKEY(CHAR)) RETURN
	GO TO 10
	END

STBKEY is a logical function to strobe the keyboard. It is
false if there are no keys down, and true if there are. If
a key is down, it is returned in CHAR. The idea of this
subroutine is to wait till someone lets go of a key. Now,
STBKEY should be declared as a logical function, and if
it is, everything works. But if it is not declared, the
compiler compiles incorrect code. The compiler should flag
this as a fatal error, but it doesn't. I tried it on the
Dec f4p compiler and the MNF compiler on the CDC, and indeed
they did refuse to compile it. Now I will list the compiler
output and show the error.
First the correct code:

FORTRAN-80 VER. 3.4 COPYRIGHT 1978, 79, 80 (C) BY MICROSOFT
CREATED: 01-DEC-80
1               SUBROUTINE BUG2
2               LOGICAL CHAR,STBKEY
3         10    IF(.NOT.STBKEY(CHAR)) RETURN
*****   0000'   LD      HL,CHAR		{point HL at CHAR}
*****   0003'   CALL    STBKEY		{result in A, -1=true}
*****   0006'   CPL			{do the .NOT.}
*****   0007'   LD      (T:000002),A	{save results into T}
*****   000A'   OR      A		{test for false}
*****   000B'   JP      Z,0000		{if false go to line 0000'}
*****   000E'   RET			{else return}
4               GO TO 10
5               END
*****   000F'   JP      10L		{go to label 10}

PROGRAM UNIT LENGTH=0012 (18) BYTES
DATA AREA LENGTH=0004 (4) BYTES
SUBROUTINES REFERENCED:
STBKEY
VARIABLES:
CHAR    0001"           T:000002        0003"
LABELS:
10L     0000'

Now the incorrect code:

FORTRAN-80 VER. 3.4 COPYRIGHT 1978, 79, 80 (C) BY MICROSOFT
1               SUBROUTINE BUG1
2               LOGICAL CHAR
3         10    IF(.NOT.STBKEY(CHAR)) RETURN
*****   0000'   LD      HL,CHAR		{point HL at CHAR}
*****   0003'   CALL    STBKEY		{result in A, -1=true}
*****   0006'   CPL			{do the .NOT.}
*****   0007'   LD      HL,T:000001	{point to memory loc. T}
*****   000A'   CALL    $T1		{copy floating acc. to T}
*****   000D'   JP      Z,0000		{if .false. loop 0000'}
*****   0010'   RET			{else return}
4               GO TO 10
5               END
*****   0011'   JP      10L		{go to label 10}

PROGRAM UNIT LENGTH=0014 (20) BYTES
DATA AREA LENGTH=0006 (6) BYTES
SUBROUTINES REFERENCED:
STBKEY                  $T1
VARIABLES:
CHAR    0001"           T:000001        0002"
LABELS:
10L     0000'

Now since the FORTRAN library routine $T1 is supposed to copy
the floating point accumulator to memory (& test for zero?) the
value of the Z flag may or may not be what you want. Certainly
the compiler is confused about what it should be doing. Most
compilers just won't compile it since STBKEY is not a logical
function. If the compiler wanted to carry type conversion and
mixing to the max, it should have called the floating point to
byte conversion routine before the CPL instruction. As it is,
the result is random. If the value in the floating point
accumulator (which is never set and hence random) causes $T1
to return with the Z flag set, this routine goes into an
infinite loop. Indeed, the result depends on what ever floating
point operation has taken place before this subroutine was
called. The result for me was an undetected bug that poped
up months later when some other unrelated subroutine was
changed. Finding it took almost a week. While this would
seem to support the case for strong type checking in
a language, what we have here is one the few places FORTRAN
is supposed to do type checking, but the compiler failed to
do so. So watch out for this one, it can really sneak up
on you.

The second bug also sent me up the wall. If you plan to
only use the Microsoft linker it will not affect you.
But if you play around with the relocateable binary
it will cause trouble. I ran into this with my own
linker which links to disk instead of memory, so I
can link a program that runs all the way up to the
top of memory. FORTRAN and MACRO80 store common block
names differently. The first character of a common
block name stored by FORTRAN has bit 8 set. MACRO80
does it right. This drove me crazy since my linker
claimed that there were two different common blocks
but printed the same name on the map. My linker now
mask characters in names so bit 8 is ignored. Hope
this very long article may save some of you some
grief in the future.

				Rich Piner
				Purdue Physics Dept.