     These three programs all do the same thing, as precisely the
same as I could make them.  There were naturally some compromises,
but I think that they will illustrate well how three programming
languages compare.

     The comment that heads the listing for ADFREE.ASM tells the
story.  This started out as a BASIC project, which wasn't too
difficult, as the code was provided by Mocrosoft (page 174 of the
PDS 7.1 Language Reference).  But two projects spun off from this: 
a DIR replacement (one of the things wrong with my favorite 3d
party DIR replacement was that it couldn't handle numbers larger
than 32M; all sorts of strange answers came up for total space and
free space when I used it on my new 120M drive), and this cross-
language project.  

     The only comment on the basic program is that I had a moment's
pause with adding 65536 to the DX and BX registers, until I sat
down and did a little math.  My calcualtions showed that, if all
three of the multiplier registers (AX, CX, and either BX or DX)
contained the maximum (65536), the total capacity of the drive
would be 2.48 X 10^14 bytes, or 248,000 Terabytes.  I don't believe
I've even seen a 2 Gigabyte drive, yet, so DOSs method leves plenty
of room for growth.

+++++

     Writing the program in C was almost as straightforward,
although I had some false starts because of my relative lack of
familiarity with that language.

     One of my design considerations was that I wanted to duplicate
as much as possible the functioning of the BASIC program in the
other languages.  For that reason, I specified the totalspace and
freespace variables as floats, to correspond to BASIC's SINGLE
type.  I went ahead and used C's long type for bytes in sector and
sectors in cluster; I could have used unsigned integers in C--
that's one of its advantages.  I suspected that using longs as
opposed to floats would not make a significant difference in
processing speed, and I wanted to test mixed-numeric type
operations (it worked--that is, I succesfully combined long
multipliers into a float result).

     C provides built-in _dos_getdrive and _dos_getdiskfree
functions (in MSC, QuickC, and Turbo C), but I wanted to use a
generic function that resembled BASIC's INTERRUPT.  Again, C offers
choices.  The intdos function will generate any INT 21h call you
could want. BASIC's is more generic, still, but I finally decided
to use intdos as opposed to int86, which is perhaps most similar to
BASIC's INTERRUPT function.  Again, I suspected that all intdos did
that int86 didn't do was put 21h in register AX automatically, and
I couldn't see a big speed difference here.  However, I did see a
potential difference between my program moving data from registers
to memory and whatever underlies C's _dos_getdiskfree doing that
(to use _dos_getdiskfree, you must first declare a structure which
contains fields for bytes in sector, sectors in cluster, clusters
available, and clusters in drive.  When the call returns, the
structure is filled).

     Some other differences between C and BASIC began to make me
aware of just how much more C was designed for this type of
programming than was BASIC.  The plethora of system calls was one
big clue.  This program could have been written in about 10-12
lines, using those calls.  This is a pretty clumsy C program, as C
programs go.

     Then again, formatting the output was almost too easy in
BASIC.  There isn't even any of BASIC's power formatting, aside
from PRINT USING, in the output, and I couldn't find any simple way
to duplicate even that in C (or assembler); I had enough trouble
just getting the spacing between output elements similar, and the
format of output numbers (not exponential) nearly the same.

+++++

     Again, in adapting the algorithms to assembly language, some
compromises had to be made.  For instance, I couldn't get a macro
to format the output to work, so I engaged some direct-to-screen-
memory procedures that I had on hand (most of which are adapted
from Peter Norton's Assembly Language Book for the IBM PC) to get
the output format close to what BASIC had produced.

     My major challenge in writing this version of the program was
dealing with long integers (I toyed with the idea of trying to use
floating point numbers here, but after a long look at the floating
point information in the MASM 6.00B, I decided that learning to
handle four-byte integers would be quite enough.

     The head comment refers to "the things the books leave unsaid
. . . ."  This refers to the fact that, although the manual says
clearly enough that two-byte multiplications lead to four-byte
results in DX:AX, it doesn't say a bloody thing about
reconstructing a readable number from that.  It also says some
things about scaled operations that make some sense, but apparently
don't apply in all circumstances.

     Consider:  I finally reconstructed the result of the
multiplication with:

     mov   WORD PTR tot, ax
     mov   WORD PTR tot[2], dx

Now, if this is scaled, these commands should move dx into a
location two WORDS away from where ax began in tot, and tot would
look something like this:

     aaaaaaaaaaaaaaaaa0000000000000000dddddddddddddddd

On the other hand, if [2] is regarded as simply an index, and the
base index is [1], then the above operation makes sense:  move ax
into the first word-sized portion of tot (the lower, or least
significant, word), and dx into the second word-sized portion of
tot (the most significant word).  Neither of these assumptions is
confirmed by the manual, although the first is implied.  All I now
for sure is that what I've got, works.

     As you can see, by far the majority of the code in the
assembly program is taken up by display-formatting procedures. 
Some of the procedures in the files CURSOR.ASM and VIDEO_IO.ASM are
not used, but so many of them are interdependent that it was
simplest just to include the whole file.  The resultant .COM
program is only a fraction over 1K long, so I don't feel any great
guilt over taking up too much space.

     A note:  most of the procedures in VIDEO_IO and CURSOR were
written using the QuickAssembler that comes packaged with Microsoft
QuickC version 2.51.  It's a fine little assembler, and anyone
needing no more than to be able to write some subroutines to
support their C or BASIC programs will do just fine with it. 
You'll see, however, that write_long_decimal was written using
MASM.  One of the things you can do with MASM that you can't do
with QuickAssembler is in the very first line after the header:

write_long_decimal  proc    uses ax bx cx dx si di

In QuickAssembler, the "uses" clause is much more restricted, and
the equivalent to what this clause does in this procedure would
look like this:

     push  ax
     push  bx
     push  cx
     push  dx
     push  si
     push  di
     .
     .
     .
     pop   di
     pop   si
     pop   dx
     pop   cx
     pop   bx
     pop   ax

All of this is accomplished in MASM by "uses . . ." and "ret."

+++++

     Well, that's about all I can think of to say about this little
adventure.  Unfortunately, I waited too long to write this after
doing the project, so some of it has gone a bit cold for me.  I did
have a lot of fun doing it, and I learned a lot about C and
especially the assembler.  If this gives you any message at all, I
actually hope it gives you two.  First, BASIC is a language capable
of serious work, and results not too different in size and speed
from C (granted, I'm comparing BASIC's Professional compiler with
the C Quick compiler, but I have a strong feeling that the BASIC
PDS would stack up well against MSC).  Second, the best way to
learn about programming is to *do* it.  I was lucky to stumble upon
a project which involved fairly limited goals--it enabled me to
concentrate on one or two (at most, three) facets of each language
that I was not too familiar with, and not get lost in a morass of
functions, calculations, output parameters, etc.

If you have any questions or comments, my Compuserve address is 71543,3533. 
I log into the IBMPRO forum usually at least once a week; I can also be found in
the MSBASIC, MSLANG, and GATEWAY forums.

Happy coding!

Brian Rogers