Contents of the ASMPROCS.TXT file
Basm Tasm Mangle and Spaghetti It
(A brief and simplified explanation of assembler interfacing to Turbo C++.)
(This article is intended for "REAL" DOS programmers:
those who don't eat quiche or drive little plastic cars.)
by: Victor E. Cummings
Trademarks contained herein are attributed to their respective owners.
This is a frequently asked question: just when and where should
I use assembler interfaces in my C programs? With the introduction
of Turbo Assembler and Turbo C++, this question becomes even more
difficult. The facilities that Tasm offers and the inclusion of
Basm the internal inline assembler make the interface so versatile
and easy that the question is not how but why and where and what
method of many do I use?
This article is for the programmer who wishes to add assembler
interfaces to C programs. With the introduction of MASM 6.0 it is
increasingly possible to do the reverse with ease. MASM 6.0 got
a marginal review from PC Magazine, but I'm not sure that I agree.
It offers loop constructs similar to a higher level language which
work gracefully, and they have many good examples included with the
assembler that you can modify for your own use. Tasm 2.5 just does
not offer that. The idea of creating assembler programs with a few
C interface routines is beyond the scope of this article, though
calling C routines from assembler is discussed. If you would like
to add higher level constructs to Tasm so you have that facility,
The MS-DOS Developer's Guide by the Waite Group offers a tool kit
which does just that, and may indeed have been where Microsoft got
If you are an assembler programmer using C interface routines, it
is doubtful that you have downloaded this article in the first
place, because the scope is too small for you.
Wherever possible this article is written at the 7th grade level
so that you may quickly get the information you need without long
The GAZINTAS and the GAZOWTAS:
GAZINTA: What GAZINTA here >
Also mathematical term
[origin obscure] >>>
GAZOWTA: What GAZOWTA there
Where ever possible, the GAZINTA and GAZOWTA method of definitions
will be used in the following explanations. This context is used
to add some humor to a dry subject, but not to insult your intel-
ligence. The discussion does not get into a lot of detail, but
attempts to help the reader gain the basic concepts quickly.
When to use Basm:
Basm is the assembler which is internal to the new Turbo C++
compiler. It has obvious limitations which are documented in the
manual. Where is Basm. Basm works silently. No message is given
by the compiler unless Basm is unsuccessful in compiling your
inline statements. Simply stated: if you have existing statements
which include the #pragma inline directives then remove them. I
have provided an example by Al Stevens which I have converted to
Borland C++ 2.0 code. In the example, the #pragma inline statement
has been removed. Compile the example "IBMPC.CPP" by using the
command line: bcc -c ibmpc. Then remove the comment preceding
#pragma inline, and the compiler will produce an assembler version
of the file and call Tasm to assemble it. The Basm compiler works
more efficiently to produce the code without having to produce
assembler output and then assembling it. The result is a faster
compile with identical output.
Inline assembly is really used at its best as in this example. It
should be used when only a few assembler statements are needed and
where time is of the essence as in waiting to write a character
after a video retrace.
Inline assembly is useful for this purpose. Inline assembly allows
more than it really should. You can even use it to call a C
function. In a word: don't. If you need to do something that
complicated, you should consider making an assembler call. It is
really easy to do with Turbo Assembler 2.5 so why not? The most
you will want to do is pass a few variables to the inline code and
let it work fast and return.
When would I want to use Tasm with the #pragma inline directive?
Don't use it where Basm will work. If you can remove it, then do.
Your code will compile more quickly. If you wish to see the result
of your assembly for debugging purposes then use the -S command
line option supplied with the compiler to get an assembly output
for your file and stop the assembly process. The IBMPC.CPP file
is a good file to try this with, because it does not include many
of the library routines, and it will give you a simple example to
study to discover how inlines are handled by the compiler. The
resulting IBMPC.ASM file has been included in this archive.
What is a mangled name?
Examine the resulting file produced with the -S compiler directive:
IBMPC.ASM. The name is descriptive. If you look at the resulting
label names created by the compiler, you will see that the compiler
has mangled the heck out of them as the name implies. The way that
the compiler mangles the names is not well documented in the
compiler documentation. The compiler tells you to create the
assembly output in this manner to study the output. They include
this as a training measure for the mangled names without having to
add to the mass of their manuals which are already quite bulky.
If you need to write assembler interfaces which will be used in
object oriented programming style, then you may produce the
function header for the function first in your C++ code. Then
compile the file using the -S compiler directive. This will give
you the mangled name to use in your assembly code commented above
by the header that your created. Then to speed this up you can
just insert your code into the code that was started for you by the
compiler. Let the compiler do the work for you. I have provided
an example called FICTION.CPP which contains some headers for some
fictional functions. When you are designing your application, and
you decide that assembly interfacing would be the way to go for
several of your functions, then you may use this technique. I
compiled the FICTION.CPP file to get the FICTION.ASM file contained
in this archive.
When I looked at the assembler output that I saw, it really made
me as a REAL DOS programmer mad. Someone at Borland really decided
to mangle the heck out of my public names! Well if the compiler
wants mangled names, I might as well let it mangle them for me.
One thing that I was really happy about: my fingers get tired
every time I have to type push bp, and the compiler already started
the code which I can snip. Really clean no? Do these guys at
Borland ever take a lunch break? The compiler even commented the
assembly code and added only the bare essentials which I would have
needed to type anyway. It even inserted my local variable names
in as comments. If the guys at Borland had taken one less lunch
break, I would have taken me two less milliseconds to set up my
local stack for the assembler call. The compiler already
calculated the ret instruction for the pascal call and even will
insert the references to the base pointer if you initialize your
variables. Then all you have to do is make the references to the
base pointer (bp) into EQU statements which you can then reference
by name. What could be easier.
When designing an application, and you just know that you are going
to need an assembler call, then just code the header for the
fictional function, initialize all the variables and compile with
the -S compiler option and snip the stub for your function. An
example that was created in about 40 seconds from the assembler
output is contained in this archive and is called SNIP.ASM. I
added only a few changes to make a very optimal stub for my
The hard part:
The hard part is where do you use assembler interfacing and where
do you not. If your program is working fairly nicely and at a
speed you are happy with then leave it in C. But you get into the
coding and you find that there is one spot which is just too
SLOOOOOOOOOOOOOOOOOOOOOOOOOOOOOW then you should resort to
assembler. In my next article for Real DOS programmers entitled
"Its Got To Be Assembler Here-->" I'll furnish you with a working
example of where assembler can not be avoided with the equivalent
C++ code that you can use in your programs.