Macros
Volume Number: 2
Issue Number: 3
Column Tag: Assembly Lab
Macros for McAssembly
By Paul F. Snively, Columbus, IN, MacTutor Contributing Editor
Question: What do you get when you combine the MDS assembler, linker,
RMaker, PackSyms, and a mini-make utility all in one 39K program?
Answer: McAssembly, from Signature Software.
This new development system comes complete with Apple's Edit, McAssembly,
three versions of McBug, and an entire disk full of files which were licensed from
Apple covering everything from the low RAM equates and OS and Toolbox equates to
interface routines for MacinTalk, AppleTalk, Graf3D, and the RAM based serial driver.
As you can see, McAssembly represents quite a step up for me (a veteran
MacASM user) in terms of complexity and power. I've always ranted against MDS, so
why am I using a very MDS-like system now?
First of all, I'm getting into more esoteric climes in terms of what I'm trying to
do with the Mac. MacASM is extremely good at what it promises to do, namely allowing
the user to easily and quickly develop stand-alone Mac applications.
MacASM lacks the ability to do some things that I now find myself wanting to do,
such as write desk accessories and link object code with code produced by other
development systems, such as TML Pascal (more about that later). In addition,
McAssembly maintains two strong advantages that MacASM had over MDS - speed and
more importantly (n my case, anyway), size. I am, after all, a 512K one drive user.
Let's talk about this new assembler. Edit is by now the de facto standard
Macintosh editor, so I won't talk about that here.
The best way to talk about McAssembly is menu by menu, so
Fig. 1. The File Menu
The file menu controls execution of the major components of McAssembly: the
assembler (called McAsm when referred to alone), the linker (called McLink when
referred to alone), and the job controller (no, it's not called McJob, it's just the job
controller).
Choosing "Assemble" brings up the standard file dialog with a list of all files with
an .Asm extension. Selecting a file causes McAsm to assemble the file, generating a .REL
file.
Choosing "Link" brings up the standard file dialog also, but this time it shows
files with .Lnk and .Job extensions (I'll explain the apparent contradiction a bit later).
The .Lnk and, in this context, .Job files are linker control files, and choosing one causes
McLink to try to link together the .REL files that it specifies.
The "Run job" option shows only .Job files. .Job file execution is different
depending upon whether the user selected the file from "Link" or from "Run job.
A linker control file is really just a specific kind of job control file. All that is
in a linker control file is a list of the .REL files to be linked (any filenames not ending
in .REL will have the extension added automatically), segmenting information (in the
form of $ [ P ] [ L ] lines, where $ is the segment break specifier and P and L are
optional "Purgeable" and "Locked" flags, respectively), filenames of resource files to
be linked in (preceeded by a "%" - great if you are in the habit of creating your
resources with ResEdit, for example), and the name of the resulting resource file
(preceeded by a "/").
Job control files, on the other hand, are more powerful, but are still simple.
They can contain comment lines, which start with an asterisk ("*") as well as all of the
other kinds of lines. That is the only visible difference, and it's not really a difference,
since .Job files can be specified from the "Link" menu option. There are, however,
other, more subtle differences.
For job control files executed via "Run job," if the filenames have no extensions
the job controller does not assume one. Instead it assumes that the file is to be both
assembled and linked if at all possible. Files with .REL extensions are only linked.
If the /filename line is supplied the job controller assumes that there needs to be
a link phase. Otherwise only the assembly phase is executed.
Now for the interesting part: if a filename in a job control file has no extension
and there is a / line for the resource file specification the job controller will attempt
to assemble the .Asm file if 1) the .Asm file is presently online and there is no
corresponding .REL file or 2) the modification date on the .Asm file is more recent than
the modification date on the .REL file (the .REL file is out of date). If the .REL file is
not out of date, the job controller will not reassemble the .Asm file. This intelligent "do
I need to assemble or not" feature is the mini-make utility that I mentioned.
Executing a job control file that has a / line as a linker control file will behave
exactly as any other linker control file - there will be no attempt to assemble at all.
Incidentally, this description of how the job controller works is somewhat at
odds with the description in the manual. The manual says that the job controller
assumes that the filenames will have no extension and does not specify what happens if
that is not the case. Fortunately, files with .REL extensions are linked but not
assembled - which is how it should be, since in some cases (Graf3D.REL, for example)
the user has the object code but not the source code.
The "Quit" option, of course, returns to the Finder.
Fig. 2. The Assembler Menu
Figure 2 shows the assembler options menu. As it is above the default options
are enabled.
"Object file" enables/disables the generation of the .REL file. This is useful for
just checking the .Asm file for obvious syntactical errors.
"Listing to printer" selects whether or not to send any output to the printer.
"Listing to screen" selects the monitor as an output device.
"Listing to file" selects a file with an .LST extension as an output device. This is
handy for use in Edit to look for the lines in error.
"Errors only listing" toggles between listing only lines in error or listing the
entire program (subject to the list directive value in the source code).
"Symbol table" toggles the option to display a list of all symbols and their values.
"Cross reference" toggles the ability to display a list of what refers to what. All
symbols are shown except local labels.
".PSM file" toggles the generation of a file of packed symbols for the program
being assembled. This probably won't be used much; but the assembler's ability to load
.PSM files will - .PSM files are compact and speed up assembly greatly, because they
require no interpretation and are only read on the first pass of the assembly.
"DEF all symbols" toggles the external definition of all symbols in the assembly.
The primary purpose of this is to have a complete set of symbols to load into McBug,
which is a symbolic debugger.
Sound good so far?
Fig. 3. The Linker Menu
The "Symbol table" option allows for the linker to display all externally defined
symbols in the module. The "Symbol table" option for the assembler, incidentally,
displays all symbols, not just the externally defined ones.
Don't get too excited about the ".MAP file output." The .MAP file that it generates
is just a copy of the module map displayed by the linker; it bears no relationship to the
.MAP file generated by the MDS linker.
"Printer output" prints linker output on the printer as well as the screen.
"McBug .SYM file" toggles the generation of a .SYM file for the program, which
can be loaded into McBug for symbolic referencing. This file format is NOT the same as
MDS' .MAP format, although the end result is essentially the same. One of my future
projects is rewriting TMON's User Area routines so that they will accept the
McAssembly .SYM file format.
A few words about McLink: First of all, no, it is not compatible with MDS'
linker, Apple's forthcoming linker, or any other linker, for that matter. Dave
McWherter, the author of McAssembly, tells me that his .REL file format is very
similar to Apple's new one, but he is leery of being the first third-party vendor to
implement a compatible format - e specially in light of the fact that Apple's linker
hasn't been released yet! If you are interested in McAssembly supporting Apple's .REL
file format, please help me try to convince him.
You MDS/Consulair linker users needn't feel left out, though. Included with the
McAssembly system is a utility that converts McLink .REL files to MDS format. Dave
admits that he doesn't like the idea; he doesn't like some things about the MDS linker,
such as the fact that it can't deal with BR type instructions (BRA becomes JMP with the
MDS linker, for example). Also, his utility cannot as of yet convert named resources -
the name is lost in the conversion. This is a minor thing anyway, but he may come up
with a version that will solve that problem (it revolves around the fact that with MDS
resource names are symbols whereas with McAssembly they are not). The conversion
is one way - McLink -> MDS Link and not vice-versa. Dave says there are some things
that his linker does that MDS doesn't and vice-versa, which doesn't surprise me. One
of the things that McLink allows the user to do is to specify an offset from A5 at which
global allocation for the module is to begin. The pseudo-op that does this - A5OFF -
affects the current module and any subsequent modules that don't have A5OFF's of their
own. Another nice little feature is that if a .REL file contains a standard BNDL
resource, McLink will automatically set the bundle bit on the resulting resource file.
More about resources in a moment. Also, McLink is blindingly fast compared to MDS
Link!
Fig. 4. The Jobs Menu
Figure 4 shows the "Jobs" menu with the default options enabled. "Stop if Asm
error" does exactly that - assembly stops if there is an error during the assembly
process.
"No link if Asm error" causes the link phase to be bypassed if there were any
assembly errors. Both of these options, and their rationales, are fairly
self-explanatory.
"Force assemblies" is the non-obvious one. It causes the assembly phase to be
executed whether the .REL files are current or not. The reason for this is that
McAssembly has an INCLude pseudo-op which can include other source files. What
happens if the user changes an included file? The file that includes it does not show a
new modification date, so the job controller ordinarily would not assemble it if a
current .REL file was available. Thanks to the new include file, though, the .REL file
wasn't really " current" anymore. With "Force assemblies," modified include files can
be reassembled without loading and saving the including source so as to force a new
modification date.
Fig. 5. The Beeper Menu
The Beeper menu is simple, too. Enabling the beep causes McAssembly to beep
whenever it encounters the end of an assembly, a link, a job, and/or an error.
Fig. 6. The Transfer Menu
The Transfer menu is pretty straightforward. "Edit" gets the user there, and
"Other" allows the user to choose any online application. Incidentally, Edit's Transfer
choices are "hardwired" as strings in the code, even though the menu itself is a
resource - bad news. That means that you have to rename McAssembly "Asm" on your
work disk if you want to be able to get there from Edit. Reports are that Apple has
contracted with Bill Duvall to revise Edit and MDS to be fully HFS compatible.
Presumably, this means the "hardwired" strings would be removed and placed in
resources or in some way made compatible with the new standard file package. The
current version of McAssembly is 3.2, which is fully HFS compatible on the Mac Plus,
except for the MDS Edit program problem, which is licensed from Apple and supplied
on the McAssembly disk.
That covers all of the menu items and should give you some ideas about
McAssembly's capabilities. Now let's take a look at some of the pseudo-ops that
McAssembly places at the user's disposal.
A5SEC and A5END are the pseudo-ops that delineate the module's global variable
area. The pseudo-ops surround a collection of DS pseudo-ops and serve to
automatically make referrences to the labels defined relative to A5. A5SEC and A5END
are actually specialized versions of BASE.
BASE causes one or more labels to be referred to relative to a given address
register whenever that label appears alone or with an additive offset. Incidentally, the
first version of the assembler that I received had a bug - the additive offset could only
be a constant, not a label. In other words, if you BASE A0,ioFlUsrWds and try to use a
line such as CMP.L #'APPL',ioFlUsrWds+fdType (a real life example from Launch
Doc), the result is CMP.L #'APPL',$20 instead of CMP.L #'APPL',$20(A0). This has
been corrected.
The A5SEC and BASE pseudo-ops make it possible to forget about what address
register you are dealing with and make the use of offset labels (which abound in Mac
development systems) far more natural. It would not be difficult to BASE offsets from
A6, for example, giving the user a convenient local variable capability. I'll give some
specific examples of this capability later.
Some other important pseudo-ops are NOLOC and LOCSYM. NOLOC causes local
label scoping to behave the same way as MDS's. This is helpful, since without it the
user would have to insert a LOC pseudo-op immediately next to every major label in the
code to get the same effect.
LOCSYM allows the user to define the local label character. McAssembly
normally uses the period as the local label specifier, but once again for the sake of MDS
compatibility LOCSYM "@" can be used to set the local label character to be the same as
MDS's.
We've talked about the assembler, the linker, the symbol packing function, and
the job controller. Now let's take a look at resource definition in McAssembly.
Dave McWherter apparently took a hint from Mainstay (the people behind
MacASM) with his resource generation. The resource compiler is an integral part of the
assembler itself, and there's no particular reason why you couldn't use the assembler
strictly as a resource compiler (no code), nor is there any reason why you can't put
assembler source code in a non-CODE resource (meaning that writing desk accessories,
new INIT resources, new FKEY resources and the like is a snap - no more RMaker TYPE
DRVR = PROC)!
McAssembly's resource compiler has two basic modes - standard resource
compilation and user defined resource compilation.
Standard resources start with the delimiter $$ and have no ending delimiter.
The supported standard resource types are: ALRT, BNDL, CNTL, CURS, DITL, DLOG,
FREF, ICON, ICN#, MENU, PAT , PAT#, STR , STR#, and WIND.
User defined resources start with the delimiter [[ and end with the delimiter ]].
They can be of any type and can contain any valid McAsm data and/or code.
Any resources defined in McAsm source files must come after the program's code.
If the user attempts to add code after resource definitions errors will result.
Furthermore, if you use the linker control line "%Filename," where Filename is the
name of a pure resource file, it must also come after any code that is to be linked. The
bottom line is that non-CODE resources are always last in McAssembly.
The application signature is a good example of a user defined resource. A
signature is nothing more than a STR255 resource by another name. A type is chosen
and the TEXT pseudo-op is used with the # option, giving the STR255 type string, e.g.
[[ LDOC,0
TEXT # "Launch Doc 1.0
]]
Standard resources look like this:
$$ FREF,128
APPL
0
|
Notice that the programmer does not need to know the size (word, long, etc.) of
the resource item, only its type. A | indicates a null string.
All but a tiny fraction of MDS programs can be assembled with McAssembly
simply by putting A5SEC and A5END around the globals (and moving them to the front
of the file, if necessary), adding NOLOC and LOCSYM "@" to the front of the code, and
converting any resources from RMaker format to McAssembly's format (it's easy) and