Those were the days – part 3

In today’s post we will take a look at IBM Personal Computer Fortran compiler version 1.00 released in January 1982. This post is part of a series in which I try to get experience of what it was like to program in the early 80s. As the last time, I am going to use my IBM PC clone with two 360KB floppy drives and 256KB memory.

The first thing I’ve noticed is that IBM PC Fortran 1.00 is distributed with 3 floppy disks similarly to IBM PC Pascal 1.00. However upon inspection of disk #3 I saw something unusual. Besides FORTRAN.LIB, the disk contained LINK.EXE as well. Back then the linker was distributed with the operating system and in January 1982 the only available version of PC DOS was 1.00. However the linker, distributed with IBM PC Fortran 1.00, was version 1.10. This was quite unusual as PC DOS 1.10 would be released a few months later in May 1982. I compared both linker version 1.10 files and confirmed that they are identical. At this point I was tempted to start using PC DOS 1.10. Until now I used PC DOS 1.00 and switching to PC DOS 1.10 would made my work easier as it supports double-sided 320KB floppy disks. At the end, I decided to reuse the floppy disks from my previous work with IBM PC Pascal 1.00, even though I could reduce the number of floppy disks in half if I upgrade to PC DOS 1.10. The main reason for this decision was to avoid making new bootable floppy disks as the process is cumbersome.

Here is how I organized my floppy disks:

  • Disk 1 (bare minimum PC DOS 1.00)
    • FOR1.EXE
    • EDLIN.COM
  • Disk 2
    • FOR2.EXE
    • COMMAND.COM
  • Disk 3 (IBM PC MASM 1.00)
  • Disk 4
    • FORTRAN.LIB
    • LINK.EXE (version 1.10)
    • COMMAND.COM
    • DEBUG.COM
  • Disk 5

The workflow is exactly the same as the one described in the previous blog post about IBM PC Pascal 1.00. IBM PC Fortran 1.00 is a Microsoft product rebranded for IBM and this explains the similarity between both products.

Once the floppy disks were set up, it was time to decide what program should I write. Just because of Fortran reputation I decided to plot some functions on the screen. As for me, this is more or less recreational blog series, I decided to plot Batman logo using mathematical functions so it kind of fits into Fortran spirit. Here is a screenshot of the end result.

While I had experience with MASM and Pascal for the previous projects, this time I didn’t have much experience with Fortran. I knew Fortran programs use fixed format, there are predefined column ranges for comments, labels, various kind of statements and so on. As a kid, I remember drawing on Fortran coding sheets/forms. Back then my father used to program in Fortran and he explained some details, but it is fair to say I preferred computer games to programming. Even today you can find Fortran coding sheets like these ones (though modern Fortran does not have fixed program format).

As for the actual coding, I can say EDLIN did a fine for the job. I had to learn to count spaces in the beginning of each line, but it easily became a habit. I was surprised that DO statement cannot be used with REAL type (well, not so surprised in hindsight). A simple IF + GOTO construct was good enough workaround for my program. However, I can imagine this would become a problem in more complex programs. Another thing that grab my attention was COMMON statement. I still don’t know if it is a good practice, but if used sparingly it seems to reduce the complexity. Funny enough it is implemented as LINK segment, a practice well known from large assembly programs. So if it used with a priori known naming convention it could seriously reduce the complexity. The integration with IBM MASM 1.00 was done mostly smoothly. According the documentation IBM Fortran passes all parameters by reference. This is all good and fine, just create new frame, save and restore all registers (it is long to explain but technically it is possible to only save and restore BP, SP and DS, but you are walking on thin ice doing so) and unwind the stack on exit. However I am pretty sure I hit a weird bug in the compiler/linker combo. I doubt anyone (sane) nowadays will program with IBM Fortran 1.00 + IBM MASM 1.00 but if you have problems with dirty registers try to rename the registers you use in the assembly part of the program. Hard to isolate but definitely a bug. However there is another bug that I managed to isolate. Checkout this program.


$STORAGE:2
PROGRAM GREET
INTEGER I
DO 100 I= 1, 1000
CALL MYSUB(I)
100 CONTINUE
END

SUBROUTINE MYSUB(I)
INTEGER I
WRITE(*, 200)I
200 FORMAT(1x,'I: ', i4)
RETURN
END

Depending on how much memory you have, this program will crash at some point with the following error

? Error: No Room in Heap
Error Code 2001
Line 5 In MYSUB Of TEST.FOR
PC = 25F:14, FP = F43E, SP = F432

The reason for this might be obvious for experienced Fortran programmers, but the RETURN statement at very end of MYSUB makes the compiler to generate buggy code.

I mean, if you don’t support this language construct then catch the error during the first compiler pass and don’t produce buggy OBJ file.

I’ve hit two relatively nasty compiler bugs in 120 lines of code. This clearly shows how buggy the compiler is. Another complaint I have is that the compiler generates slow code. I mean really slow. Checkout the following video.

On the left side of the video is the same program compiled with IBM PC Fortran 2.00 which came out two years after version 1.00. It has fewer bugs, supports PC DOS 2.00 and most importantly supports 8087 floating-point coprocessor and my IBM PC clone has one. When the program is compiled with $NOFLOATCALLS flag and linked with 8087ONLY.LIB it is blazingly fast. When I use IBM PC Fortran 1.00 the actual speed is demonstrated on the right side of the video. If the program is compiled with IBM PC Fortran 2.00 it executes for 7 seconds. If it is compiled with IBM PC Fortran 1.00 it executes for 4 minuted and 46 seconds. In both scenarios the hardware is the same. The video on the right is recorded on MartyPC emulator (which is equivalent speedwise to my IBM PC clone) because I can’t be bothered to film actual hardware for almost 5 minutes.

Considering the compiler quality, one may ponder on the idea whether IBM/Microsoft would have been better off delaying the release of the compiler with two years. Maybe just one year would be enough. I would probably be more forgiving if I didn’t have 8087 coprocessor. I don’t know how much it cost in the early 80s, but having spent money on hardware and not being able to use it, doesn’t feel good. After all, Fortran had built its reputation for being able to squize the performance out of the hardware. I won’t be surprised if I am able to implement this program more efficiently with IBM PC Pascal 1.00. Anyway, the experience was worth it. It gave me a general feeling what it was like to program for IBM PC in early days. One interesting thing, I’ve observed so far, was that I often had to use assembly language in order to implement the required functionality. While there is nothing wrong with it, for my next project I will try to avoid it if possible. I have very fond memories from LOGO programming language so maybe that will be my next project.