home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Archive Magazine 1996
/
ARCHIVE_96.iso
/
discs
/
shareware
/
share_46
/
sasm
/
Docs
/
Manual
< prev
next >
Wrap
Text File
|
1994-04-03
|
165KB
|
3,436 lines
SSSSS AAAA
SS AA AA
SS AA AA SSSSS mmm mmm
SSSS AA AA SS mm mmmm mm
SS AAAAAAAA SSSSS mm mm mm
SS AA AA SS mm mm mm
SSSSS AA AA SSSSS mm mm mm
Version 1.54
The Simple Assembler for the Archimedes
Copyright David Holden 1991,92,93,94
_______
____|__ | (R)
--| | |-------------------
| ____|__ | Association of
| | |_| Shareware
|__| o | Professionals
-----| | |---------------------
|___|___| MEMBER
CONTENTS
Page
Preliminaries
Introduction ........ 1
Licence to Use ........ 2
How to Register ........ 2
Advantages of Registration ...... 2
Licence to Copy ........ 3
Using SAsm
Use with floppy discs ........ 4
Command line syntax ........ 5
Null Parameters ........ 6
Source Filenames ........ 7
Reconciliation of Wildcards ..... 8
Order of Assembly ........ 9
Length of Source File ........ 9
Line number space ......... 9
A short demonstration ........ 10
The Source File
Source File Syntax ........ 11
General ........ 11
Important warning ........ 11
Warnings and Errors ........ 12
Comments ........ 12
Descriptive text ........ 13
Large source files ........ 14
Basic keywords accepted ........ 14
Directives ........ 15
Basic variables ........ 16
#ORG ........ 16
#SIZE ........ 16
#END ........ 16
#TYPE ........ 17
#OBJ ........ 17
#ERRFILE ........ 17
#LIB ........ 17
#VERBOSE ........ 17
#QUIET ........ 18
#INCLUDE ........ 18
#INSERT ........ 19
#AREA ........ 19
Multiple data areas ........ 21
#LISTON ........ 22
#LISTOF ........ 22
#NOENHANCE ........ 22
#ENHANCE ........ 22
#XREF ........ 22
#NOXREF ........ 22
#XRFILE ........ 23
#SWION ........ 24
#SWIOFF ........ 24
#CLI ........ 24
#LABELFILE ........ 25
CONTENTS
Page
Defining registers etc. ........ 26
Defining constants ........ 26
Conditional Assembly ........ 27
LDM/STM with Writeback ........ 28
Assembly Loops ........ 28
Using the OSET variable ........ 29
Assembly Listing ........ 30
Creating a Listing file ........ 31
Listing file directives ........ 31
Scope of listing ........ 31
Labels
Global Labels ........ 32
Local Labels ........ 32
Local Label Scope ........ 32
Local Label Example ........ 34
Forward Branch to 00 ........ 34
Enhanced 2nd Operand ........ 35
Extra Mnemonics
DW and DD ........ 36
DB ........ 37
Basic variables and DB ........ 38
ADRL ........ 39
MOVL ........ 39
DIV ........ 40
Macros
Macro Functions - Pro/Con ...... 42
Expanded Macros - Pro/Con ...... 42
Macro Names ........ 42
Expanded Macros
Defining expanded macros ........ 43
Macro parameters ........ 43
Local labels in macros ........ 44
Special features ........ 44
Examples ........ 45
Errors in expanded macros ....... 46
Macro Functions
General ........ 47
Built-in Functions ........ 47
FNgap ........ 48
FNset ........ 48
FNadr ........ 48
FNmov ........ 48
CONTENTS
Page
The Macro Library
Using the Macro Library ........ 49
The 'L' parameter ........ 49
The 'V' parameter ........ 50
SAsm$Lib OS variable ........ 50
Preparing a Library ........ 51
Length of Library file ........ 51
SAsm and the Desktop
New features ........ 52
Using from the desktop ........ 53
Problems and Questions
Reporting and diagnostic ........ 54
Speed of operation ........ 55
Memory usage ........ 55
Notes on Local Labels ........ 56
Common problems ........ 56
Release History ........ 60
Registration Form ........ Endpiece
Page 1
-=O=- INTRODUCTION -=O=-
A long time ago when I found I needed more facilities than the Basic
assembler offers I tried Acorn's AASM. My personal opinion of AASM is
that it is overpriced, clumsy and, for many purposes, LESS powerful
than the (free!) Basic assembler. I therefore decided to write my own,
provisionally titled BAsm. As usual it had to be fitted in with other
things, and meanwhile I needed an assembler. I continued to use the
Basic assembler for short utilities and AASM for longer ones. Soon I
found I was using AASM less and less as I gradually added bits to the
Basic assembler to give the additional facilities I needed.
To make life easier I wrote a 'pre-processor' for the Basic assembler
as a stop-gap until I finished BAsm. Gradually it was improved and
with each improvement the need for BAsm receded and work on it assumed
a lower priority. Eventually my stop-gap program assumed a life of
it's own and had become so powerful that it could do just about
everything I wanted. At this point I realised it would be useful to
others as well. I re-wrote the program, making lot's of improvements,
and named it SASM - Simple ASseMbler for the Archimedes
Don't be put off by the word 'Simple'. Unless you are re-writing
Impression SAsm will probably fulfil all your needs. Simple is
intended to describe its ease of use. Its main limitation is that it
cannot produce output in AOF (Acorn Object Format) for linking to 'C'
or other languages. If you want to write in 'C' I'm afraid you are
stuck with ObjAsm or !AS (APDL disc B150) until I get around to
finishing BAsm. It also cannot assemble Floating Point opcodes
although you could add Macros to do this. If you really must use them
(I've never found the need) ask and I will try to include them.
SAsm is not actually an assembler. It is a pre-processor for the Basic
assembler. Don't worry about this. As far as the user is concerned
SAsm works with Text source files and behaves like a 'proper'
assembler. It has lots of facilities that the Basic assembler normally
lacks, local labels, multi-file assembly, error reovery, etc. yet at
the same time the syntax will be familiar to anyone who has used the
Basic assembler. You also have the power of Basic available with its
Mathematical, Conditional Assembly and Expression Evaluation abilities
If you are not an expert at using the Basic assembler I suggest you
read the file 'Tutorial'. It won't teach you to write machine code but
it explains the use of Macro Function and Conditional Assembly with
the Basic assembler helps you understand SAsm better. (SAsm actually
has another, better, Macro system as well as Basic style Functions).
Please read carefully the 'Licence to Use' and 'Licence to Copy'
before you use/copy SAsm.
David Holden
39 Knighton Park Road
Sydenham
London SE26 5RN
081 778 2659
Page 2
SAsm is SHAREWARE, it is NOT Public Domain
ssss h h aaa rrrr eeeee w w aaa rrrr eeeee
s h h a a r r e w w a a r r e
ssss hhhhh a a rrrr eeee w w w a a rrrr eeee
s h h aaaaa r r e w w w aaaaa r r e
ssss h h a a r r eeeee ww ww a a r r eeeee
-=O=- LICENCE TO USE -=O=-
This program is distributed as SHAREWARE. It is NOT Public Domain. This
means that you are only licensed to use it for a period of THIRTY DAYS.
At the end of that time you must either stop using it or REGISTER.
Failure to comply with this condition is a Breach of Copyright and is
now recognised in almost all countries as an offence.
Use of ANY version of SAsm for any TRAINING or EDUCATIONAL purposes
without payment of the Registration Fee is ABSOLUTELY FORBIDDEN.
-=O=- HOW TO REGISTER -=O=-
Registration costs just Eight Pounds. I have made the last page of this
Manual a Registration Form. Please use it when you register as it helps
me to keep my records tidy. Fill it in, preferably adding comments, and
post it to me. Don't forget your cheque for Eight Pounds. Write as much
as you wish, I do take notice of comments and suggestions.
Each assembler for the ARM processor will produce slightly different hex
values for the same assembler mnemonics. SAsm leaves its 'fingerprints'
on the code produced. I can tell if a program was assembled using SAsm.
I will take action against ANYONE who uses SAsm and distributes code
WITHOUT REGISTRATION in breach of this licence
Advantages of Registration
--------------------------
The first advantage is that you will not, of course, be breaking the
law. Registration costs just eight pounds, so it's not expensive.
However there are some material advantages.
When you register you will receive your personal copy of the latest
version of SAsm which can use external Macro Libraries This enables SAsm
to load Macros automatically during assembly. You will also receive the
tools which will let you create Macro Libraries. This makes your code
simpler because you don't need to include all the macro definitions
within it before you call them.
You will also have the right to FREE UPDATES. Once you have registered
you can return your ORIGINAL copy of SAsm to me with a stamped, self
addressed label at any time for a copy of the latest version. To take
advantage of this offer you MUST return your original disc with your
personal copy of SAsm, not just a blank disc. You will also be entitled
to free or very low cost upgrades to any future assemblers or compilers
that I produce even if these are not part of the SAsm 'family'.
Page 3
-=O=- LICENCE TO COPY -=O=-
If you are a Sysop or run a PD or Shareware library READ THIS CAREFULLY.
1. The Author retains full copyright to this program and all
the material and documentation associated with it.
2. Any private individual may GIVE copies of the UNREGISTERED
version of SAsm to his/her friends. Only PD or Shareware
libraries and BBS's which have been given permission by the
Author are permitted to distribute SAsm. Any distribution by
any organisation or for any reward whatsoever whether in fee
or in kind without permission is forbidden and will be
treated as Breach of Copyright even if the fee is merely
intended to cover costs.
3. You may not make any changes to the program or documentation
and you must include the Examples directory and its contents
and the Tutorial, Manual and all other associated files.
4. You may not make any charge for this program or for any
additional material you supply. You may charge a reasonable
fee to cover copying, media, postage, overheads, etc.
5. You may not under any circumstances distribute copies of any
registered version of SAsm. These can be distinguished
because they display the name of the registered user after
the copyright message whereas the version which may be
freely distributed displays the word 'UNREGISTERED'.
6. You must not distribute any version of the 'MakeLib'
application. This is for the use of Registered users ONLY.
If you have any problems or suggestions for improvements to SAsm please
write or phone. If you write with an enquiry please enclose an SAE. If
you prefer to telephone I am normally available on weekday evenings.
David Holden
39 Knighton Park Road
Sydenham
London SE26 5RN
081 778 2659
SAsm was produced by a member of the Association of Shareware
Professionals (ASP) who want to make sure that the Shareware principle
works for you. If you are unable to resolve a Shareware related problem
with an ASP member by contacting the member directly, ASP may be able
to help. The ASP Ombudsman can help you resolve a dispute or problem
with an ASP member, but does not provide technical support for members'
products. Please write to the ASP Ombudsman at 545 Grover Road,
Muskegon, MI 49442-9427, U.S.A. or send a CompuServe message via
CompuServe Mail to ASP Ombudsman 70007,3536 or FAX 616-788-2765.
Page 4
-=O=- USING SASM -=O=-
SAsm is a 'Transient' program. This means that when it is invoked by
typing it's name at the OS '*' prompt it is loaded from disc and Run.
This is not normally a problem because SAsm is quite compact, about
25K. If you have a hard disc put SAsm in your Library directory. If you
have only a single floppy drive then copy SAsm to each working disc, it
won't take up much disc space.
From version 1.30 onward you will find two versions of SAsm on the
distribution disc. One is the transient application and this is
probably the best way to use SAsm if you have a hard disc as you can
simply copy it to your Library directory and it will automatically Run
whenever you type its name. The other version is a Relocatable Module
called SAsmMod. This will be the preferred method if you don't have a
hard disc. Just load the Module by double-clicking on it and it will
then run from the RMA whenever you type 'SASM' in exactly the same way
as the transient program runs from disc. The only disadvantage of the
Module is that it will take up an extra 25K or so of RAM in the RMA.
Note that the Module version of SAsm does not actually run from the
RMA. When you invoke it the program code is copied down to &8000 and
run from there. It will therefore have the amount of RAM available that
you have set for the 'Next Slot' in the Task window.
I anticipate that a version of SAsm with a complete desktop 'front end'
will appear in the near future but for the present you can run it from
within a 'Task' window if you wish.
Use from floppy discs
---------------------
Although SAsm will obviously operate much faster from a hard disc it is
perfectly satisfactory when used on a machine without one. In fact it
was deliberately designed with floppy disc operation in mind. If you
have enough memory then you could create a large RAM disc to hold all
your files. The disadvantage of this is that if you modify the source
files and suffer some sort of crash before you remember to save the
modified files to disc you could lose part of your work.
Because SAsm uses only fast block file operations to load the source
and save the object files it will still operate quite fast from floppy
discs. If you use the Module version of SAsm this will save the time
overhead of loading the assembler itself each time.
The slowest file operations are associated with error, listing and
label cross-reference files as these are written line by line. The
obvious solution is therefore to direct all of these to the RAM disc
where the operations will be very much faster than a floppy. As these
files are normally only needed temporarily it will not matter if they
are lost. To further reduce disc access time you could save the object
file to the RAM disc and copy your macro library (if used) there.
Page 5
Command line syntax
-------------------
The full syntax of the command string for SAsm is;
SASM <source file list> [object filename] [error filename] [LXVQSNFA]
Only <source file> is compulsory, the others are optional. This means
after *SASM leave one or more spaces and then type the name of your
source file(s). You can have as many as you like, separated by commas.
The full meaning of <source file list> is quite complex and for the
complete explanation read the section titled 'Source Filenames'.
Because SAsm uses spaces a delimiters between command line fields you
must NOT put any spaces in your source file list.
After the source file(s) leave a space then type the name of the Object
File. This is the name that will be given to your assembled code when
it is saved. If you don't type an Object Filename SAsm will assemble
all the files but won't save the finished product. It may seem strange
that you should wish to do this but if you just want to check for
errors or find out how long the finished code is it can be useful.
The next parameter is the name of the Error File. Unlike the Basic
assembler SAsm will display error messages and try to continue with
assembly if it can. If you have many errors the first ones will soon
scroll off the screen and get lost. If you define a name for an error
file all the error messages will be sent to the file. This can be
loaded them into your Editor with the source code in another window so
you can find and correct them. If you use a Task Window you could
'capture' error messages in this but a separate error file is neater.
After the three filenames you can type one or more single letter
parameters or 'switches'. These can be in in upper or lower case. If
you use more than one they should be separated by spaces. Most of these
duplicate or interreact with Directives in the files and so the
descriptions here are rather brief because more information will be
found in the section on Directives.
The 'X' parameter will cross reference (X-ref) all labels in the source
and report any duplicates. If a duplicate is found a warning message is
displayed with the name of the label and the line number at which it
occurs. You can include this each time but normally it is only needed
the first time you link all your files as sometimes a duplicate label
is perfectly valid. For example I often use 'loop' or 'bak' repeatedly
and don't want a screen full of warnings. You can create a list of
duplicate names as a file by use of the #XRFILE directive (see later).
'L' is used to force SAsm NOT to load any Macro definitions from the
Library, even if one exists. See the section on the Macro Library for
an explanation of this.
'V' will make SAsm 'verbose' when loading Expanded Macros from a
Library. As each macro is loaded it's name is displayed. This is not
normally needed but it is included in case you want to check whether
SAsm is using a macro defined in the file or from the Library.
Page 6
'A' makes SAsm produce an Assembler Listing file. If 'A' is followed by
a filename this will be used, otherwise it will be saved to the current
directory with the name 'ListFile'. If you do wish to use the default
name for a listing file make sure that the 'A' command is the last item
on the line, otherwise it will 'grab' the next parameter as a filename.
You will find more information on assembler listing files later.
(NB- The more obvious 'L' isn't used for a listing file because it was
already allocated by the time this feature was included.)
'F' formats an assembler listing file with labels at the left and
instructions indented.
'S' switches on processing of SWI names. This is described fully in the
section on the SWION/SWIOFF directives.
'Q' makes SAsm Quit after pre-processing is complete but before
assembly. This is useful if you get a serious error during assembly as
it lets you produce a listing without the possibility of a complete
'crash' during assembly.
'N' will list all global label Names after pre-processing. This will be
in the form of list on the screen in alphabetical order. This switch
will stop a label cross-reference check so don't use 'X' and 'N' at the
same time. As this list is likely to be rather long you can use the
LABELFILE directive to save it to a file if you wish
Null Parameters
---------------
You will notice that these names must appear in order. So what do you
do if you want an error file but no object file?, or a X-ref but no
Error or Object file? If these switches are defined within the source
there is no problem but most of the time this will not be the case as
you would only need x-ref or listing files for de-bugging purposes.
To permit switches to be used at the command line when one or more of
the file names is not present SAsm accepts the ~ character or any
filename beginning with ~ as the equivalent of no filename.
For example, to assemble the source file 'My_Prog' without producing an
object file but listing all errors in the file 'Errors' you could use -
*SASM MyProg ~ Errors
If you use the '~' character in the object filename position you will
not get an object file even if a name is defined in the source file.
There is therefore a further alternative. If you use '!' as an object
filename SAsm will only produce an object file if the name is defined
in the source. The '!' character is interpreted as 'only produce an
object file when an OBJ directive exists'. This permits you to use
switches and an object file without needing to type a source file name.
Page 7
Source Filenames
----------------
The source filename list can be a single filename or a series of names
separated by commas. DON'T use spaces to separate the names because
SAsm regards a space as a field delimiter. This is important because if
you do use a space between source filenames and if SAsm is able to
successfully assemble the first file(s) the next name will be taken as
the object filename. This will result in the code being saved with this
name which will DESTROY the source file of the same name. Normally this
can't happen because the fact that some of the files aren't loaded will
produce errors but it could, so beware!
Most users will probably use a 'make' file with 'INCLUDE' filenames to
assemble a project but you should understand the full command line
syntax to ensure that you know exactly how SAsm operates with
wildcarded filenames.
To assemble the files Start, Middle and End in that order into the
object file Code you would use;
*SASM Start,Middle,End Code
This assumes the files are in the Currently Selected Directory (CSD).
Each name can of course have a path as well. If you have some standard
sub-routines called Subs in directory $.Source.Routines you could use;
*SASM Start,Middle,$.Source.Routines.Subs,End Code
SAsm loads the files in the order in which the names appear and treats
them as if they were one big file. You can therefore break the source
up into small chunks and sub routines which are easily edited. You may
find you have lots of standard routines that you want to assemble with
your program and you can put these in one or more separate files and
assembles them with each project.
The easiest way to avoid all this typing is to program a function key
with the command. For the previous example if you type;
*Key 5 *SASM Start,Middle,$.Source.Routines.Subs,End Code|M
you need only press F5 to assemble your code. This saves the repetitive
typing but as the length of a function key string is limited to 255
characters it may not be enough to accommodate a long list of
path/filenames. SAsm therefore accepts wildcards in the source file
list. If you use a common part in all the filenames for a project this
feature can often enable you to assemble all the required files with
just a single wildcarded name.
Page 8
Reconciliation of Wildcards
---------------------------
It might appear that no 'filtering' of wildcards in filenames is
necessary. If you put all the source files in sub-directory 'Source' of
the CSD then typing *SASM Source.* Code would assemble them all
into the object file Code with no problems. In real life things aren't
that simple. For example, if you make an alteration to one of your
source files but want to keep the original in case the change doesn't
work (always to be advised!). You make the alterations, change the name
of the original, and assemble the code. The only problem is that SAsm
would assemble BOTH files, the original and the new. You could avoid
this problem by moving the original to another directory but this would
soon become very tedious.
SAsm has a rigid system of deciding which files to assemble. This was
designed to work with the way I write my source files. If you don't
like it let me know and I will try to accommodate your preferences but
please try my way first, it's the result of a lot of experience and you
might find you like it.
SAsm works it's way through the list in order. It first finds all the
names which fit the wildcarded first name in your file list.
SAsm rejects any file that doesn't have a filetype of 'Text' (FFF) or
'Data' (FFD). This avoids trying to load a previous object file or
other non-source file if it was saved to the same directory. As all
text editors on the Archimedes save output as 'Text' by default this
should not be a problem. If you do import a file from some other source
then its type will probably be 'Data' and if not you can easily change
it. If you get a 'File not found' error but can see that the file
exists it is probably because its filetype is not &FFF or &FFD.
The remaining files which fit the wildcarded name are then examined and
loaded IN ALPHABETICAL ORDER. Any file which has a digit 0-9 at the end
of its name is examined and if it has the same name as the previous
file but with a different number it is ignored.
What this means is that if you give all your source files a name ending
in a number the file with the LOWEST number will be loaded and the rest
ignored. This works because the lowest number is also the first
alphabetically. I start out at 99 and work my way down, so each version
is progressively called Name_99, Name_98, Name_97 etc. This system
operates beautifully with TWIN (Acorns non-desktop text editor) because
if I type 'Name*' as the filename to load into TWIN it will load the
one with the lowest number, ie. the latest. Within the desktop the
latest version will always be the first file in the directory viewer.
When all the files with names which fit a wildcarded filename have been
loaded SAsm will get the next name on the list and so on until all the
names have been dealt with.
Page 9
Order of Assembly
-----------------
Remember that SAsm assembles the files which can be matched to each
wildcarded name alphabetically. To return to the previous list with
'Start, Middle and End' if you use '*' to match all of these files then
they will be assembled in the order 'End, Middle, Start' which is not
what is required. As it is normally only the first and sometimes last
files whose order is important it is fairly easy to ensure that they
are assembled in the correct order by placing an extra digit at the
start of the name. For example renaming the files 'aStart, Middle,
zEnd' would ensure that they are assembled in the correct order while
retaining meaningful names.
Since SAsm expands and reconciles wildcarded filenames in this way you
don't need any complicated 'make' utilities to assemble a long list of
source files. In fact the additional facilities offered by the INCLUDE
directive make this even simpler.
Length of Source Files
----------------------
Because SAsm loads all the files into memory at once in might seem that
the total length of these files could not exceed the usual 640K (or
whatever you have set 'Next Slot' to) which is available as a Task. In
fact this is not the case. As SAsm loads each file it removes all the
spare spaces and assembler comments. If, like me, you indent every line
and use lots of comments you will probably find your source files
shrink to about 60% of their original size. Even allowing for the
memory required for variables, the assembler commands etc. you should
find that SAsm can load over 1MB of source with the usual 640K slot. If
you are writing programs which need more than this then perhaps you
should be writing your own assembler and trying to sell it to me!
Line number space
-----------------
When the pre-processed code is passed to the Basic assembler it must be
given line numbers so that Basic can understand it. This means that 3
bytes must be added to the start of each line. If there is not enough
room for this SAsm will attempt to relocate the file in memory. This is
unlikely to happen unless you have more than about 10,000 lines.
It is possible that there isn't enough RAM available for relocation and
in this case SAsm will be unable to continue. If this happens there are
two possible solutions. The simplest is to make more RAM available.
Bring up the Task Manager window on the desktop and increase the size
of the 'Next Task' allocation. On a 1Mb machine you may need to 'kill
off' some tasks to be able to do this. If you cannot make more RAM
available you will need to reduce the number of lines in your source
file. There is no point in removing comments, column indents etc.
because by the time this error occurs they will all have been stripped
by SAsm anyway. However each line removed saves only three bytes so you
will need to remove a lot of them to make any real difference.
Page 10
A short demonstration
---------------------
Copy the file SAsm and the complete 'Example' directory to a blank disc
in drive 0. Now press F12 to leave the desktop or CTRL-F12 to open a
Task Window and type 'MOUNT :0' at the OS '*' prompt. To assemble the
demonstration program type;
SASM Example.H* Hello
The disc drive will start and after the SAsm copyright line you should
see the messages;
Loading Source Files:
Example.Hello_A
Example.Hello_B
Example.Hello_C_50
Pre-processing completed - starting assembly
Pass 1
Pass 2
0 Errors
Code &xx bytes - Saved as 'Hello'
You will find that a new file 'Hello' has appeared on the disc. To run
this program, which just displays a couple of messages, type 'Hello'.
If you examine the contents of the directory Examples you will find
that as well as Hello_A, Hello_B and Hello_C_50 (and several other
files) there is Hello_C_52. Since this file has a higher number than
Hello_C_50 it was ignored.
Now repeat the exercise but hold down the SHIFT key when you press
RETURN after entering the SAsm command line as previously. Everything
will seem as before but this time when you type *Hello to RUN the
Object code some of the messages will be different. This is a simple
example of Conditional Assembly, some of the code being changed if the
SHIFT key is held down during asssembly.
I suggest that you load these three files into Edit and examine them.
They are not a good example of compact or well written code but they do
illustrate the layout of a multiple SAsm source file. You will notice
the use of the Conditional Assembly section which produces the two
different versions. Note also that branch instructions can be used to a
label in another file demonstrating that labels are global.
You will also see the use of a Macro Function 'print_string'. This
would be more efficiently coded using OS_Write0 but it illustrates how
Macros Functions are written and used.
The files 'Local' and 'Immed' are examples to illustrate the use of
local labels, SAsm's simplified 2nd operand instructions and Expanded
Macro's. These may be assembled and examined in a similar manner.
Page 11
-=O=- THE SOURCE FILE -=O=-
Source file Syntax
------------------
I will assume that the reader is familiar with the Basic Assembler.
Reference will be made to it and attention drawn to differences between
it and SAsm where they occur. Although the syntax used by SAsm is
similar to the Basic Assembler this applies only to the actual assembly
language itself. You can forget about square brackets, OPT, P%, O% and
all the things that are necessary before you can use the Basic
Assembler. The biggest change is that if you have previously used the
Basic Editor the source files for SAsm, like all assemblers, are TEXT
files and must NOT have line numbers.
One of the nice features of SAsm is this similarity. This isn't an
accident. Firstly SAsm actually uses the Basic assembler to do much of
the work. Secondly it was designed from the start to be a 'step up'
from the Basic assembler so even it's most advanced features will be
very quickly mastered by anyone who is familiar with the Archimedes
'built-in' assembler.
You won't therefore need to spend ages learning a whole new language
and you will be able to convert your old Basic assembler programs into
SAsm format very easily and quickly. Normally this takes only a few
minutes with a straightforward program.
General
-------
In the following section you will find references to various commands
being separated by spaces. In general if your Editor uses a Tab
character (ascii 9) to separate text into columns this character will
also be accepted. This may not be specified each time to avoid constant
repetition. If you do find that a Tab character won't work but a space
will please tell me and I'll try to make it work.
In this Manual references are made to the 'hash' character '#' (the
character above the '3' on the main keyboard). If that appeared in your
printout as a pound sign then your printer is set to the English
character set so you will just have to read the file as if it had
printed a hash. There are no pound characters in this Manual.
Important Warning
-----------------
SAsm makes use of the Basic integer variables O%, P% and Q%
O% and P% are used conventionally by the basic assembler. Q% defines
the OPT setting during assembly. It is therefore vital that you do NOT
use or manipulate any of these variables unless you are absolutely sure
of what you are doing.
Similarly the upper case names ADDR, TYPE, OSET and SIZE are reserved
words and must not be used as Basic variables.
Page 12
Warnings and Errors
-------------------
In the following sections reference will be made to Warnings, Errors
and Fatal Errors.
Warnings are issued if SAsm finds you have omitted or wrongly placed a
directive. The code will still be assembled and saved. Warnings will
not be written to the Error file.
Errors are faults from which SAsm can recover but which make the code
useless. Unlike the Basic assembler SAsm will try to continue after an
error as there may be others to report, but the assembled code will not
be viable so no Object file will be produced. However if a Listing file
was specified then this will be produced.
If SAsm finds an error in the first pass it will not attempt a second
pass. You may therefore need two attempts to correct all the errors.
A Fatal Error is an error from which SAsm cannot recover or which is so
serious that there is no point in continuing. An error in a Macro
Function or a missing file are examples of Fatal Errors.
Comments
--------
SAsm defines a comment as EVERYTHING on a line after a semi-colon ';'
or a backslash '\'. SAsm therefore conforms to the syntax used by most
assemblers which differs from the Basic assembler. The Basic assembler
is almost unique in using the colon ':' as a statement delimiter. While
SAsm still recognises ':' and allows more than one mnemonic on a line
Basic regards ':' as the end of a comment and tries to assemble
anything on the line after a ':', even if the ':' is in a comment. For
example the following line using the Basic assembler;
mov r1,#0 : \ mov r1,#1 : mov r2,#2
would be assembled as mov r0,#0 followed by mov r2,#2 The middle
instruction would be ignored because Basic recognises the '\' and
regards it as a comment but continues assembling when it finds the ':'
later in the line. Using SAsm you would get ONLY mov r1,#1 as
everything on the line after the '\' is a comment.
The exception to this is where a semi colon (;) is not preceded by a
space or a Tab character (ascii 9). This has been done so that you can
use ';' in Basic PRINT statements to display information during
assembly. If you do use ';' in a line to define a comment make sure
that it is preceded by a space or a Tab or it will cause an error.
If you want to use more text than can be fitted into a normal comment
then see the next section.
Page 13
Descriptive text
----------------
Sometimes you may want to put a block of descriptive text somewhere in
a source file. This is often required before a major routine to
describe what it does, entry conditions, register state on exit, etc.
Normally this is done by preceding each line of the text with a ';' or
'\' but this is rather tedious, and it's easy to miss a ';' and get
assembler errors. It is also a nuisance if you want to edit it later
because you must fiddle about with all the ;'s if you reformat it.
Most high level compilers permit blocks of descriptive text between
certain markers and the text is ignored by the compiler. This is very
convenient and I have therefore introduced this feature into SAsm using
the curly brackets, { and }, as the delimiters.
The { must be the first non space character on a line. Everything up to
the terminating } will then be completely ignored. The opening { can be
followed by text on the same line or on a line of its own.
There is an important proviso with the closing bracket. It MUST be
preceded by a space, Tab, or be the first character on a line. If this
is not done it won't be recognised as terminating a descriptive text
insert and you'll get errors.
The reason for this is that these two characters may also be used to
'blank out' sections of code you don't want to assemble. Instead of
needing a ';' in front of every line you can enclose the entire block
between { and }. This makes it a lot easier to avoid assembling
debugging code, etc. when you no longer need it but to restore it
simply when you do. If you use this feature for this purpose then, if
the requirement for a space before the closing } did not exist, there
would be a problem with LDM and STM instructions where the register
list is enclosed in the same characters. If you make sure that you
don't have a space before the closing } with your LDM and STM
instructions (not difficult) then you can use these characters to blank
out code containing those instructions.
To make this even easier SAsm will ignore a closing } if it is the
first character on a line (unless, of course, it is actually the
terminator of a pair of {}'s). This would be an error under all normal
circumstances so it would never exist naturally. If you do use this
feature to blank out a section of code then to bring the code back into
use you need only delete (or 'comment out') the opening {, the closing
one will be ignored.
Obviously if a } with a preceding space exists in the section you want
to blank out then you may get unexpected errors. The most likely cause
of this is a } in a comment, but this should be easy to check.
In normal use only problems you are likely to encounter is if you
forget the closing } or if you don't precede it with a space. In this
case SAsm will either completely wipe out all the code up to the next
closing } it finds, which will probably produce a whole series of
errors, or it will quit with a Fatal Error if it comes to the end of
the file before it finds a closing }.
Page 14
Large source files
------------------
Archimedes basic can load files in text format and this is the way that
SAsm normally operates. However Basic always insists upon numbering
programs in this format in 10's. The trouble with this is that Basic
can't accept line numbers greater than about 65,000 so this would limit
the maximum source file size to around 6500 lines. This only applies to
programs in text format, if the program is numbered in 1's instead of
10's then it can be over 65,000 lines long which is big enough for any
eventuality.
For this reason if a file is longer than about 6500 lines it is
necessary for SAsm to tokenise it instead of leaving this process to
Basic. This is completely automatic, smaller programs will be left
untouched and larger ones will be tokenised. However in order to
simplify the SAsm code and to make the operation as fast as possible
this routine is not nearly as comprehensive as the system used by basic
itself. This is not normally a problem as most of the Basic keywords
would never be used in an assembler source file. All of the graphics
commands and many others have been omitted and will produce errors if
they are used.
There is a possible conflict between the Basic operators AND, EOR and
OR and the assembler mnemonics AND, EOR and ORR. In theory the SAsm
tokeniser can distinguish between these when used as mnemonics and when
used as operators but circumstances could exist where it could become
confused. Obviously this can't happen if the mnemonics are written in
lower case. In fact with larger programs you are advised to use lower
case for ALL mnemonics as this makes the tokenising very much faster.
There is also room for confusion if you use any variables with names
that include Basic keywords. Basic itself will always recognist
'theORy' as a variable but the SAsm tokeniser might, under some
circumstances, try to tokenise the 'OR'. With well written source code
this shouldn't be a problem as normally variables have lower case
letters or use capitals as word delimiters but you should be aware of
the possibility of problems.
Basic keywords accepted
-----------------------
These are the only Basic keywords that can be used in an SAsm source
file longer than 6500 lines. There is no reason why others can't be
added, I just couldn't think of any reason to include them. If you do
have a real need then please tell me.
ABS, AND, ASC, CALL, CASE, DATA, DEF, DIV, ELSE, ENDCASE, ENDIF,
ENDPROC, ENDWHILE, EOR, EVAL, FALSE, FN, FOR, GET, IF, INKEY, INSTR,
LEFT$, LOCAL, MID$, MOD, NEXT, NOT, OF, ON, OR, OTHERWISE, PRINT, PROC,
READ, REM, REPEAT, RESTORE, RIGHT$, SPC, STEP, STR$, STRING$, SYS,
THEN, TO, TRUE, UNTIL, VAL, WHEN, WHILE
Page 15
Directives
----------
It is possible to include 'Directives' in your source. In fact some
directives are necessary for the proper operation of SAsm. Any line in
which the first non-space character is '#' is a directive. If SAsm
doesn't recognise what follows the '#' it will assume it is a valid
Basic statement and the line after the '#' will be passed to Basic.
You can use SAsm without any preliminary directives in your source
file. Unlike the Basic assembler you can begin by writing mnemonics
straight away. If you do this SAsm will start assembling your code to
run from '0000'. This doesn't matter as SAsm will normally produce
position independent code unless you have included specific references
to addresses within your source.
The '#' character can have spaces before and after it to improve
legibility if you wish, they will be ignored, but it MUST be the first
non-space character on the line. Directives should be the only item on
the line although you may include comments.
All directives are case insensitive. Where a directive is to be passed
to Basic it's case and syntax must conform to that required by Basic.
Where a comment is included in a directive which is to be passed to
Basic it can still be preceded by ';' or '\' rather than REM, but see
the note under 'Comments' above.
There must be at least one space after a directive where it is followed
by one or more parameters.
Directives and Basic variables
------------------------------
Because of the way that SAsm passes unrecognised 'directives' to Basic
this could create difficulties if you use any of the SAsm directives as
Basic variables. This will not of itself cause problems, for example,
there is no reason why you could not have a register called 'org'.
However you should be careful how you define such items, eg. using -
# include = 7
to set a Basic variable 'include' to 7 would create difficulties
because SAsm would recognise 'include' as one of its own directives and
try to interpret it. However -
# fred = 6 : include = 7
would be OK, because SAsm wouldn't recognise 'fred'. Similarly -
# include=7
# include%=7
# include_it = 7
would also be OK because in all cases there is no space following
'include' as required by SAsm.
Page 16
In general you are advised to avoid using any SAsm directives as
variables or constants because this could be a source of strange
errors. Remember also that all SAsm directives are case insensitive so
this would apply to include, INCLUDE, Include, etc.
The upper case versions of the directives ADDR, TYPE and SIZE, are
reserved words and must not be used as variables anywhere in your code.
#ORG
Defines the address the code will be assembled to run at. The syntax is
# ORG <number> where <number> is a valid address. <number> will be
assumed to be in hex whether or not it is preceded by a '&' character.
If no #ORG directive is found assembly will start at location 0 and a
warning message will be displayed. The #ORG directive must obviously
appear before the first assembler statement. If an #ORG directive is
found after this a warning message will be displayed and the code will
be assembled to start at location 0. This does not apply if you have
defined TYPE (see later) as 'Absolute', 'Module' or 'Utility' because
these filetypes, which are the most commonly used, all have 'standard'
load and execution addresses.
There must be at least one space between the word 'org' and the number
which follows. This applies to all the following directives.
Note - ORG replaces the ADDR directive used in early versions. ADDR is
still supported for backwards compatibility but ORG should be used in
new work as ADDR may be dropped in the future.
#SIZE
This advises SAsm of the expected size of the code so it can reserve a
large enough buffer for it. The full syntax is #SIZE <number> where
<number> is the estimated maximum size of the code. <number> will be
assumed to be in hex whether or not it is preceded by a '&' character.
If there is no #SIZE directive before the first assembler statement a
warning will be given and 64K will be allocated for the code. Any #SIZE
directives after the first assembler statement will be ignored.
#END
This takes no parameters and should be placed at the end of your
assembler and before any Macro Function definitions. Anything after
#END will be passed to Basic without the need for a '#' at the
beginning of the line. When SAsm finds #END it assumes it has reached
the end of the code and everything else is Macro Function definitions
If DEFFN is found at the start of a line indicating that a Macro
Function definition has been found before an #END directive a warning
will be given and all subsequent lines will be passed to Basic.
Page 17
#TYPE
This defines the filetype you wish your assembled code to have. Syntax
is #TYPE <filetype> where <filetype> is a valid Archimedes filetype. If
<filetype> is a number it should be in hex, though it need not be
preceded by a '&' character. If it is a textual representation of a
filetype it may or may not be in quotes, for example -
# type FF8
# type "Absolute"
# type Module
If you do not include #TYPE the assembled code will be saved as an
absolute block of memory with no filetype. The most common filetypes
are &FFC for a position independent Utility, &FF8 for an Application to
be loaded and Run at &8000 and &FFA for a Relocatable Module.
Unlike the previous examples #TYPE can appear anywhere in the source.
If more than one #TYPE directive appears the last one will be used.
#OBJ
Defines the name of the Object file. The syntax is #OBJ <filename>
where <filename> can be any valid path/filename. If you type an object
name at the Command Line it will override any #OBJ directive. You can
therefore include an #OBJ directive in the source but assemble a
different version if you choose by typing an Object name at the CLI.
#ERRFILE
Followed by a path/file name this defines the error filename to be
used. Again an error filename typed at the command line will override
this directive.
#LIB
Defines the Library file to be used. LIB should be followed by a
path/file name. This overrides any Library defined in the SAsm$Lib
variable.
Using #LIB without a filename will force SAsm NOT to use a Library and
so is equivalent to the command line 'L' switch.
# VERBOSE
Equivalent to the command line 'V' switch to force display of names of
macros inserted from a Library. The advantage over the 'V' command line
switch is that it can be inserted at any point and so need not show all
the expanded macros, only those used after the directive is used.
Page 18
# QUIET
Switches off display of macro names. You can use this with 'verbose' as
often as you wish to switch on and off display of expanded macro names.
#INCLUDE
This allows additional files to be 'included' as well as the ones
specified at the command line. The word INCLUDE should be followed by
at least one space and then a single filename. Unlike files loaded from
the command line only the first file which matches the required name
will be used and no checks will be made on its filetype.
The INCLUDE directive in SAsm is different from its equivalent in 'C'.
SAsm does NOT 'insert' the file at the point at which the directive
occurs. There is another directive INSERT which performs this function
but this is not intended to be used for assembler source files.
INCLUDE creates a 'queue' of INCLUDE filenames. When it reaches the end
of the current file it goes to this list and loads the first name in
the queue. When that file has been dealt with it loads the next name
and so on until the queue is empty. If one of the 'include' files
contains more INCLUDE directives these names are added to the END of
the queue. When the queue is empty SAsm returns to the filenames
specified at the command line and carries on as before. INCLUDE files
can therefore have further INCLUDE directives which can contain their
own INCLUDE's and so on.
If you have a complex program which consists of lots of small pieces of
code and sub-routines you can create a 'master' file which will contain
the #ORG, #TYPE etc. directives and then a list of #INCLUDE directives
to define the files required to make up the program. This operates in
the same way as 'Make' files for other assemblers and compilers. SAsm
will simply load each INCLUDE file in your 'primary' file in the order
in which you have listed them. As INCLUDE files are subject to similar
discrimination to filenames typed at the command line the 'trailing
number suffix' system can be used to assemble the latest versions.
For example, a file containing just the following would assemble the
named files with the lowest trailing numbers in the chosen order.
# type Absolute
# size 1000
# include start_*
# include middle_*
# include end_*
Page 19
#INSERT
This is used to 'insert' the file whose name follows into the code at
that point. Unlike INCLUDE it is inserted directly into the code at the
point at which the directive occurs. No filetype checking is carried
out and only the first file found with a matching name is loaded.
The file is not inserted during preprocessing but during assembly. It
therefore cannot contain SAsm format assembler source but would
normally consist of data required by the code. This could be sprites,
screen images, templates, text or any other form of data. It could even
be pre-assembled machine code although this is not likely to be usual.
To reduce disc access the assembler merely 'makes room' on the first
pass and actually loads the data on the second. Code or data following
an INSERT directive will automatically be double-word aligned in case
the file is of 'odd' size.
#AREA
This is intended to simplify setting up Data Area consisting of a
series of bytes or words to be accessed using LDR Rx,[<reg>,#<offset].
Normally this is done by reserving an area of memory in some way and
defining each individual offset line like this -
.my_data db *80,? ;reserve 80 bytes
# first = 4
# second = 8
# third = 12
and so on. You would then use instructions such as -
ADR R8,label ;make R8 point to the data
LDR R4,[R8,#second]
STR R2,[R8,#third]
The problem with this method of setting up a data area is that every
offset must be calculated 'by hand' and if you make a mistake the data
can become corrupted during the running of the program. Also if you
want to change the size of an item, for example, to increase a byte
sized item to a word, then every other offset will need to be
recalculated. Not only tedious but easily leading to mistakes.
The AREA directive is designed to make this type of data area much
easier to define. It automatically sets the value of each offset and
calculates and allocates the amount of space required. The syntax is
very simple, but you will need to take careful note of exactly how it
works to avoid errors.
At present (version 1.53) this directive works perfectly but it may not
be very 'robust' and so it is possible that if you use it wrongly you
might get strange errors. I will try to introduce more error trapping
in future and add some extra features.
Page 20
A data area is declared by the #AREA directive and this is followed by
the name to be used to refer to it and the size of the first item, eg -
# area my_data 4
'my_data' will then become a normal Global Label and can be addressed
just like any other label. You can use LDR/STR instructions with it if
you wish or ADR/ADRL to make a register point to it.
The important part comes next. Following the first line you can
introduce a series of 'pointers' into this data area, defining the size
of each as you do so. Note that unlike the normal method of doing this
you define the SIZE of each item, not its offset from the start. To
reproduce the previous example using the AREA directive -
# area my_data 4
first 4
second 4
third 4
# ea
Note that the AREA block is terminated by an #EA (End Area) directive.
This will produce exactly the same results as the previous example but
it is MUCH easier to set up. Instead of working out the offset of each
pointer all you need to do is to follow its name with the size of the
item that you want to put there. In this example each item will have
four bytes allocated. If you wanted single bytes you would use -
# area my_data 1
first 1
second 1
third 1
# ea
Obviously sizes can be mixed. Note that te number in the first
declaration line defines the size of the first item which would
normally be accessed by -
LDR R0,[<reg>] or LDR R0,[my_data]
As this item has an offset of 0 there is no need to define one for it.
If you really do want to always refer to the first item with an offset
then simply set the 'size' of this item to '0' so that the pointer
defined on the following line will have an offset of 0.
If you mix the sizes of items within a data area you may need to reset
the pointer to ensure that word size section will be word aligned. This
can be done in the normal way with an ALIGN instruction. In fact this
instruction works differently when used in this context but its action
is the same as usual.
Page 21
To illustrate this using mixed sizes as in the previous example -
# area my_data 1
first 1
align
second 4
third 4
# ea
This will ensure that 'second' and 'third' have word aligned values.
Note that this will ONLY be true if the START of the data area is word
aligned. This will normally be the case but if in doubt use 'align' on
the line BEFORE the #AREA directive. Similarly if you have used odd
sizes items in your data area you should follow it with 'align' to
ensure that any code or data which follows is word aligned.
Within the confines of an AREA directive, ie. between #area and #ea,
only the structures shown above are permitted. No assembler mnemonics
or any other directives or statements are permitted. Items must be
placed one per line exactly as shown. You can have comments, preceded
by the usual ';' or '\', either following an item on the same line or
on lines of their own. You can have blank lines if you wish.
If any line in an AREA begins with a '#' character that will terminate
the area. In fact, you don't really need an #ea directive, # on its own
will do. However you are advised to use #ea for clarity. If an AREA
operation is terminated before the end because of an error you may get
various error messages depending upon exactly what the cause was. You
may also get an '#EA directive found when not in Data Area' message.
At present the data in the area is not preset to any value. I may add a
feature to do this at some time in the future.
Multiple data areas
-------------------
You may have realised that every offset defined by the AREA directive
becomes a Global Variable. This makes it possible to define a series of
identical data areas and use the same offsets to access them. This
would be particularly useful in programs which operate upon more than
one set of data at the same time.
To return to the previous example if you subsequently used -
.label_2 db *40,?
to reserve some space for a second area. Now -
ADRL R8, label_2
LDR R1,[R8,#second]
will address an identical offset in the second area.
Page 22
#LISTON
This will create a file which will contain an assembler listing. It may
be followed by an 'F' which will produce a 'formatted' listing. The
listing file will not start at the beginning of the source code but at
the point at which the LISTON directive occurs. (See later section on
Assembler Listing)
#LISTOFF
Marks the point at which the assembler listing file will cease.
#LISTFILE
Sets the name to be used for an assembler listing file.
#NOENHANCE
Switches off the second operand enhancements (see later). Included for
untidy programmers who insist upon using instructions like MOV 1,2.
#ENHANCE
Switches second operator enhancements on again. This is the default.
#XREF
Switches on label cross reference. Once again the advantage of this
over the 'X' switch is that it only takes effect from the point at
which it appears.
#NOXREF
Switches off label cross reference. Can be used as often as required
with the previous command to toggle x-ref on and off.
There is an obvious interaction between the 'X' command line parameter,
the XREF directive and this directive. The x-ref will begin at the XREF
directive unless the 'X' command line parameter is used, in which case
it will start at the beginning of the first file. It will finish at the
NOXREF directive if one appears, if not at the end of the last file.
XREF and NOXREF can appear more than once in the files. The function
will simply be switched on or off as they are encountered. Beware of
leaving NOXREF directives scattered in your files. They could cause the
x-ref to be disabled without you realising it and therefore prevent
duplicate labels from being revealed.
Page 23
#XRFILE
Followed by a filename this sets the name to be used for the label
x-ref file if this is required. If duplicate labels are to be saved as
a file they will not be displayed on screen, only the total number of
duplicated names found will be shown. If no x-ref filename directive
appears the listing will appear only on screen. If the XRFILE directive
appears without a following filename then the default filename of
'xr_file" will be used.
When shown on screen SAsm prints a message in the form -
Warning : Duplicate label '<label>' at line <line number>
where <label> is the duplicated label and <line number> is the number
of the line on which the duplicate was found. There is no need to show
the name of the file in which the duplicate was found because this will
already have been displayed as SAsm loaded it. However when a duplicate
list is saved as a file these filenames don't appear and so the name of
the file in which each duplicate was discovered will also be shown.
Note that this directive doesn't actually initiate the x-ref function.
It just ensures that if the operation is enabled either from the
command line or by the XREF directive then a file will be created. The
directive must appear before the first label in the file or the file
will not be created until the directive does appear. The obvious place
for it is at the start of the file so that if you do invoke the x-ref
function at any time the file will be available.
Page 24
#SWION
This switches on processing of SWI names. Normally if you wish to use
the textual version of a SWI it must be enclosed in double quotes, eg
SWI "OS_WriteC"
Once this command or the command line 'S' switch has been used there is
no need for the quotes, so you can simply use -
SWI OS_WriteC
It will also interpret any SWI number beginning with a '0' as a hex
number, so that 'SWI 020' would be number 20 hex, 32 decimal, and not
20 decimal.
There are potential problems with this system which is why it is not
made the default but must be deliberately activated. SAsm assumes that
the parameter following a SWI instruction is a string if the first
character is an upper case letter (A-Z). This works because the names
of all Archimedes SWI calls begin with a capital letter. So far as I am
aware this also applies to all third-party modules. If a name begins
with a lower case letter it will not be recognised and will produce an
error. The more likely problem would arise if you define constants for
some SWI numbers. All will be well if you give these names beginning
with a lower case letter but if a name begins with a capital letter
SAsm would regard it as a text version of a SWI and this would again
produce an error.
In general you should not experience any difficulties if you ensure
that if you do wish to use a SWI name which begins with a lower case
letter you enclose its name in quotes and if you define constants for
any SWI numbers you make sure that their name does not begin with a
capital letter.
#SWIOFF
Switches off SWI name processing described above.
#CLI
Anything on the line after this directive will be passed DIRECTLY to
the Archimedes operating system Command Line Interpreter. It is
equivalent to a '*' command used in a Basic program. It is not like the
Basic 'OSCLI' command as no substitution is carried out first. You
should not put comments on the line after a #CLI directive.
Page 25
#LABELFILE
The 'N' command line switch has already been described. This switch
will produce a sorted list on screen of all the global labels that SAsm
finds in the source files. Obviously this list can be very long and so
the LABELFILE directive allows the label list to be sent to a file.
As with other filename directives it should be followed by at least one
space and then a path/file name. If the directive appears but without a
following name then the default name 'LabelFile' will be used.
This directive does not actually initiate a label listing, it just
ensures that if you do want one it will go to a file and not to the
screen. You can therefore place it in your source and if you do need a
label listing at any time it will be in the form of a file. If the list
is to be sent to a file the message-
Creating label list file '<filename>'
will be displayed and the label list will not be displayed on screen.
As with the screen display of labels they are arranged one per line in
alphabetical order. The 'sorting' of names is case sensitive so 'Exit'
will come before 'exit' and 'aAdvark' before 'aadvark'.
As well as the 'N' switch there is a 'shortcut' which will produce a
label list. If you hold down both SHIFT keys as you press RETURN when
you type the SAsm command line this will initiate a label list just as
if you had used the 'N' switch. As usual whether the list is to screen
or a file will depend upon whether you have included the LABELFILE
directive or not.
Page 26
Defining Registers
------------------
To simplify writing code it is normal to give the C.P.U. registers
names and define various other constants. In Basic this is done by
assigning the chosen name a number using the syntax <name>=<number>.
The same method is used with SAsm except that you must precede your
definitions with '#'. For example, to define register 5 as 'count' and
register 6 as 'flag'
# count = 5
# flag = 6
or alternatively
# count=5:flag=6
R13,R14 and R15 are pre-defined as 'sp', 'link' and 'pc' in upper and
lower case as these are the normal definitions for these registers. All
registers are pre defined as their equivalent 'r' and 'R' numbers.
Basic doesn't recognise a number like 'r4' as meaning register number 4
except when it is an assembler operand. If you try to pass 'r4' as a
parameter an error would be generated. With SAsm you can use r0-r15 or
R0-R15 as they have been pre defined.
You can use this method to define SWI's, offsets in a data area, in
fact anything you wish. Since these are normal Basic variables you can
use integer and string variables if required.
Defining constants
------------------
Most source code begins with a long list of constant definitions. For
example, you will probably want to give names to registers, use
variables to define the size of data areas and buffers, string
variables for program version and support file names etc. This could,
of course, be done as described above with a series of '#' statements
but it is more elegant to use a standard Basic procedure.
Remember that everything after the #END statement is just normal Basic.
Therefore you can write a perfectly ordinary procedure after #END to
define all your constants. Then, at the start of the first file, before
the first assembler statement, put a call to this procedure, eg.
# PROCdefine
This will call the procedure and define all your constants.
There is one unusual feature of SAsm that you must remember. Everything
from the start of the file up to the END directive is within the
assembler loop. As it is a two pass assembler all constant declarations
and procedures are enacted before each assembler pass. In the previous
example PROCdefine would also be called before the second pass. This is
not normally of any consequence unless you have deliberately altered a
variable at some stage in the program. If you have done so you should
be aware that it will be reset before the second pass.
Page 27
Conditional Assembly
--------------------
This works as with the Basic assembler. The most common method is using
IF THEN, (ELSE), ENDIF. If you are unfamiliar with this technique
please read the 'Tutorial' file which explains it.
With SAsm there is no need to bother with assembler brackets, etc. Just
put '#' in front of the lines which form the conditional block.
# IF <condition> THEN
......... ; some code
.........
.........
# ELSE
......... ; the alternative code
.........
.........
# ENDIF
Don't forget the 'THEN' at the end of the 'IF' line. The 'ELSE' section
is of course optional.
If an error occurs in a conditional section you may find subsequent
'ELSE found without IF' or 'ENDIF found without IF' errors occurring.
This is not significant, it just means the assembler has 'forgotten' it
was in a conditional section when the original error was discovered.
There is no reason why you cannot use other methods for more complex
multiple choice options. For example the CASE statement could be used.
# CASE <condition> OF
# WHEN <condition 1>
......... ; some code
.........
.........
# WHEN <condition 2>
......... ; some code
.........
.........
# WHEN <condition 3>
......... ; some code
.........
.........
# OTHERWISE
......... ; the alternative code
.........
.........
# ENDCASE
The OTHERWISE section is, of course, optional.
Page 28
LDM and STM instructions with Writeback
---------------------------------------
The LDM/STM instructions are primarily used for stack management
although they can be used for multiple register transfer to and from
memory. Usually they will be used with Writeback in the form -
LDMIA <reg> !,{ <register list> }
Using the Basic assembler it is necessary to leave a space between
<reg> and the '!' character. If this is not done then the Basic
assembler isn't bright enough to interpret the instruction correctly
and assumes that you are using some sort of contorted indirection to
define your pointer register and tries to interpret the '!' as an
indirection operator. This means that something like -
STMIA sp !,{pc,link}
is required with a space before the '!'
On the assumption that you are probably not doing anything like this
SAsm permits the use of the '!' character without an intervening space
so that the more natural -
STMIA sp!,{pc,link}
is permitted.
Assembly Loops
--------------
When using the Basic assembler it is common to use FOR-NEXT loops to
fill an area of memory, eg.
........ ;normal code
] :REM exit assembler
FOR I%=0 TO 255
[ OPT PASS
EQUB &FF ;fill 256 bytes with &FF
]
NEXT
[ OPT PASS ;back to assembler again
........ ;normal code
You could still use this method with SAsm if you wish but it is simpler
........ ;normal code
# FOR I%=0 TO 255
EQUB &FF
# NEXT
........ ;normal code again
In fact SAsm has a much better way to fill an area of memory with a
value by using the DB mnemonic.
Page 29
Using the OSET variable
-----------------------
With the Basic assembler it is sometimes required to 'poke' values into
a data area after assembly. Alternatively you may wish to modify some
data in some way. Ad you will be aware of the address of the start of
your code in memory, the offset used by the O% variable and you will
presumably have inserted a label at some convenient point as a marker
you would be able to calculate the exact location that you wish to
change. With SAsm the actual address of a location is hidden from the
user and so the variable OSET is set to give you a 'base' to use for
these purposes.
During assembly OSET is set in such a way that OSET+<label> where
<label> is any normal global label will point to the location IN MEMORY
of <label>. For example, to 'poke' the string 'version$' into the
location defined by the label 'version' you would use -
# $(OSET+version) = version$
You can, of course, add an offset to <label> if you wish. For example,
to 'blank' 256 bytes from the label 'buffer' you could use -
# FOR I%=buffer TO buffer+255
# ?(OSET+I%)=0
# NEXT
Both of these examples are, of course, contrived and the same results
could be more efficiently be produced by other means.
The most likely use for this would be to 'disguise' some text in your
code in some way. This makes it possible to compose it in plain
language when writing the code but garble it after assembly.
Page 30
Assembly Listing
----------------
SAsm will not normally produce an assembly listing. Not only would this
obscure any Error or Warning messages it also slows down assembly.
It can be useful to to see exactly what has happened to the source code
after pre-processing. For example, to check that a macro has been
expanded or a complex DB statement properly interpreted. SAsm has no
provision for displaying an assembler listing on screen. This could be
done by altering the OPT setting, directly manipulating the variable
Q%, and programmers experienced in using the Basic assembler will be
able to do this. This is not normally to be advised. Instead SAsm
allows an assembler listing file to be created. This can be loaded into
a text editor and examined at leisure. Two different layouts are
available, Standard and Formatted.
The Standard format produces a 'compact' listing with no spare spaces
or column indenting. This makes the code rather cramped and difficult
to read but it will be less than half the size of a Formatted file.
This method may be best if you are using floppy discs and require a
listing of all or a large part of your code.
The Formatted listing produces a file with labels in the left hand
column. Mnemonics are indented by 24 spaces and the operands indented
by a further eight places. This makes the code much easier to read but
it will probably double or treble the size of the file.
In both cases only lines containing assembler are reproduced and all
comments are stripped. All other lines, including blank lines, are
ignored. There is therefore no direct line-to-line correlation with the
original source file(s). (I'll include a switch to change this later).
The listing file is not saved as a 'block' but is written one line at a
time so the operation is slower than other SAsm file operations. Using
a hard disc or RAM disc even a large file will only take one or two
second but with a floppy disc it could take several. The message
'Creating listing file' will appear at the start of the operation and
it's end is signalled when the message 'Pre processing completed -
starting assembly' appears.
Creating a listing file
-----------------------
Listing files are created by typing the parameters at the command line,
by inserting suitable directives, or by a combination of both methods.
The command line parameter is 'A' (for Assembler). This should be
followed by the filename required. Remember that whatever follows the
'A' parameter will become the filename so if, for example, you also
want a label cross-reference and type an 'X' after the 'A' you won't
get a x-ref but you will get a listing file called 'X'.
If you don't follow the 'A' with a filename and it is the last
parameter typed then the default name of 'ListFile' will be used and
the file will be created in the Currently Selected Directory on the
current filing system.
Page 31
Assuming that no other directives are used this will result in a
listing file consisting of all the source files used. If you have also
used the 'F' parameter then this will be a Formatted file, if not it
will be in the compact format.
Listing file directives
-----------------------
Assembler listing files can be produced instead of or in addition to
Object and/or Error files.
There are three directives which relate to listing files, these are
LISTON, LISTOFF and LISTFILE. As their names imply these are used to
define the start point in the code from which a listing file will be
created, the end point at which the listing file will finish, and the
name to be given to the file.
LISTFILE should, of course, be followed by the path/name you wish to
assign to the file. As the listing file is not created until all source
files have been loaded it does not matter where in the source the
LISTFILE directive appears. If there is more than one LISTFILE
directive the last one found will apply. Any filename typed at the
command line will override a directive filename and in this case a
message to this effect will be displayed.
By default a listing file will begin with the first assembler statement
and finish with the END directive. Most of the time you will only need
to see a small part of the code and so LISTON and LISTOFF are used to
mark the beginning and end of the file.
If LISTON is followed by an 'F' or if an 'F' parameter was used at the
command line then the file will be formatted.
Note that LISTFILE of itself does not produce a listing file, it merely
defines the filename which will be used if a file is required.
Scope of a listing file
-----------------------
It is important to understand exactly how these commands and directives
work in order to ensure that you get a listing of the required section
of code. By default the listing file starts with the first assembler
statement and stops with the END statement. These start and end points
are modified each time SAsm encounters a LISTON or LISTOFF directive.
If there is more than one of either or both then the last one
encountered will be the one which applies.
It is therefore possible if a LISTON directive is encountered after the
last LISTOFF directive for the required start of the listing to
apparently be after the end. In this case SAsm will not be able to
produce the file and will simply display an error message.
If there is no LISTON directive the listing file will begin at the
first assembler directive and continue until the LISTOFF directive. If
there is no LISTOFF directive it will begin at the LISTON directive and
continue until the END directive.
Page 32
-=O=- LABELS -=O=-
Global Labels
-------------
All labels and constants are common throughout all files. It is
important to remember this or some very strange things can happen. With
SAsm you don't need to declare labels external, they are ALWAYS global.
Adding the suffix 'X' to the command line invokes the label cross
reference. This will check all labels and report multiple definitions.
For reasons previously explained multiple definitions of a label are
classed as Warnings only and not Errors. If like me you repeatedly use
labels like 'loop' or 'bak' to form short loops you will need to
visually check the list of duplicates for 'foreign' names.
Local Labels
------------
Since it could become tedious to invent names for all the labels you
need to make short jumps and loops a system of 'Local Labels' has been
included. These are defined in exactly the same way as normal labels,
ie. by preceding the label with a full stop. Local labels MUST be
defined at the start of the line, which is good practice anyway, and
consist of a two digit decimal number 00-99.
You are advised to read the following section carefully and ensure that
you understand exactly how this system operates. It's perfectly
straightforward and easy to use but if you don't use it properly you
will get repeated errors or branches to the wrong destination.
Local label scope
-----------------
You start each 'set' of local labels with a label '00' When SAsm finds
label 00 if 'forgets' all previous local labels. You can therefore use
the numbers 00 to 99 repeatedly and each local label will only apply
within its own section. Each time you start a new section of code or
sub-routine make the first label in that section 00 You can use label
00 even where a label is not actually needed to ensure that the scope
of the current set of local labels is ended.
Local labels can ONLY be used with Branch (or BL) and as the second
operand in LDR and STR instructions, with or without conditions, and
with the ADR or ADRL pseudo-opcode. They cannot be used within Macro
Functions but they can be used in Expanded macros.
You will soon find that you will use local labels for all the loops and
short jumps in a section, using meaningful labels where appropriate.
This makes the code much easier to follow because the 'real' labels
which define entry points and complete routines stand out.
Page 33
Using local lables
------------------
There are some features of local labels which you should be aware of.
Firstly they cannot be used as the operand of some instructions or
psuedo opcodes. As has already been mentioned they can be used with all
branch instructions, ADR, ADRL, LDR and STR. They cannot be passed as
parameters to functions or expanded macros. They cannot be used in
Macro Functions or anywhere after the END directive.
A local label only has a meaningful value when used in the correct
manner within its own 'scope'. If you define labels 00, 01 and 02 in
one section then an attempt to branch to 03 within that section will
produce an error, not a branch to 03 in the previous or next section.
Although there are up to 100 individual labels available in any section
this is far more than you should ever need. I find it best to divide
each set into sub-sections so that each loop or sub-sub-routine has its
own sub-set of labels. The first would use 00-09, the next 10-19, then
20-29 etc. This not only makes the code easier to read it ensures that
there are plenty of 'spare' labels in each set if I need to add extra
code later. You don't, of course, need to define the labels in any
particular order provided you start at 00, it just looks neater and
makes it easier to follow the 'flow' of the code. This is because a
branch to a low number will go back to the beginning of the section and
to a high number forward to the end.
Local labels are not checked by the x-ref routine. If you accidentally
use the same local label within its 'set' you will get the same
problems as can exist with any other duplicate label. This should not
be a problem in practice, especially if you define labels in numeric
order, because each set of labels will normally fit within a couple of
'screens' of code and any duplicate or out of sequence labels can be
plainly seen.
The maximum number of 'sets' of local labels allowed is over 2700,
which should be enough for any eventuality.
Page 34
Example
-------
Any Branch instruction will only reach back to the last 00 label and
forward to (but not including) the next. There can be no overlapping of
local label 'sets'. The following example should make this clear.
.00 ........ ; some code
........
.01 ........
........
........
.02 BNE 01 ; This will branch BACK to the last 01
........
........
.00 ........ ; This starts a new section of labels
BGT 01 ; Branch FORWARD to 01 in this section
........
........
.01 ........
BEQ 02 ; This will produce an error as 02 is
........ ; not defined in this section
........
BLT 00 ; Branch BACK to the last 00
.00 ........ ; Start another section
........
ADR r1,00 ; Put address of the LAST 00 in R1
ADR r2,01 ; put address of the NEXT 01 in R2
........
.01 ........
Forward branch to 00
--------------------
Consider this short piece of code;
cmp r0,#32
bne 00
........ ;code to be skipped if r0 not 32
........
.00 ........ ;rest of code
This won't work. The branch would go BACKWARDS to the last 00. You can
NEVER branch forward to a 00 label.
There are two ways to produce the desired result. You you could insert
a 'dummy' label somewhere before the branch instruction to 'reset' the
local label system, for example -
.00 cmp r0,#32
bne 01
........
........ ;code to be skipped if r0 not 32
.01 ........ ;rest of code
Page 35
The 00 label is not used but it resets the local label system so that
the branch is correctly interpreted.
An alternative is to insert a label specifically for the forward branch
just before the next 00 label.
cmp r0,#32
bne 90
........
........ ;code to be skipped if r0 not 32
.90 ;empty line with just a label
.00 ........ ;rest of code
Remember that a local label must be defined at the beginning of the
line. With the Basic assembler you could use -
.label_1 mov r0,#4 : mov r1,#5 : .label_2
This will still work with SAsm but NOT if the second label is a local
label. From the earlier example you can see that -
.90 : .00
wouldn't work. The two labels must be on separate lines.
Page 36
-=O=- ENHANCED 2nd OPERAND -=O=-
This operates on the second operand of instructions CMP, MOV, TST and
TEQ. It will work whether or not the instruction is conditional but it
can NOT be used with CMN or MVN (yet!). For it to work there must be a
space between the opcode and the first operand.
The aim is to make it easier when the second operand is an immediate
value rather than another register. The Basic assembler requires the
second operand to have a leading '#' character for it to be recognised
as an immediate value. SAsm will accept this but will also recognise
most immediate numeric operands.
If the second operand begins with a digit 0-9, an '&', a '%' or is
enclosed in double quotes SAsm will assume that it is an immediate
value whether or not it is preceded by '#'. There is also no need to
use the Basic 'ASC' prefix if a character is enclosed in double
quotation marks. For example -
SAsm Basic Assembler equivalent
cmp r0,"A" cmp r0,#ASC"A"
mov r0,020 mov r0,#&20
mov r2,"z"+1 mov r2,#ASC"z"+1
mov r2,1+"z" !Error - won't recognize "z" as an ascii value
cmpne r0,13 cmpne r0,#13
teq r0,"m" teq r0,#ASC"m"
cmp r0,%110 cmp r0,#%110
mov r0,&A4 mov r0,#&A4
mov r0,0A4 mov r0,#&A4
mov r0,A4 !Error - A4 won't be recognised as an immediate number
As you can see this makes the code easier to read and also avoids
errors when you forget to include the '#'.
Note that you can ONLY use these shortcuts when the number is obviously
an immediate value. If it is a variable you must still use the '#'.
WARNING - With this system an actual number in the second operand
position is always assumed to be an immediate value. If you really DO
mean a register you will have problems. For example, the instruction
'mov 1,3' is interpreted by the Basic assembler as 'copy the contents
of register r3 into register r1' but by SAsm as 'load register r1 with
the immediate value 3'.
To avoid this sort of ambiguity it is usual when writing ARM code to
always prefix register numbers with 'r' or 'R', but this is not
compulsory and the Basic assembler doesn't require it. If you have
fallen into bad habits and just use a simple register number then you
will have problems.
There are two possible solutions. Firstly you could mend your ways and
refer to registers properly like everyone else. Secondly you could use
the #NOENHANCE directive to disable this feature.
Page 37
-=O=- EXTRA MNEMONICS -=O=-
These are not actually mnemonics but are macros which are expanded by
the preprocessor. They are written into the code just like normal
opcodes and so this distinction can normally be ignored. One important
difference is that unlike all normal mnemonics some CANNOT have
conditional suffixes.
Some of these call the built-in macro functions and reference should be
made to these for further clarification if required.
They may all be written in upper or lower case like normal assembler
mnemonics.
DW and DD
---------
These are expansions of the normal EQUD and EQUW codes and in fact are
translated into these when expanded. The main advantage is that DW and
DD can be used to reserve a series of words or double words and not
just one at a time. These follow the mnemonic as a comma separated
list. For example -
DD 1,2,3,4,5,6
would be expanded by the preprocessor to -
EQUD 1:EQUD 2:EQUD 3:EQUD 4:EQUD 5:EQUD 6
which can save a lot of typing.
Because the line will actually become longer, which is obvious from
looking at the above example, it is possible for these codes (and the
DB mnemonic which follows) to cause the line to expand beyond the
permitted limit of 255 characters. You should therefore avoid putting
too many items on a single line.
If any of the numbers begin with a zero SAsm will assume that the
number is in hex format, whether or not it is preceded by an '&'
character. for example '20' would be decimal 20 but '020' would be
translated as &20, eg. hex 20 which is decimal 32.
Page 38
DB
--
This is a general purpose macro which replaces EQUB and EQUS and also
allows an area of memory to be reserved for data and preset to any
value if required.
In it's simplest form DB acts exactly like DW and DB but with byte
sized sections as a multiple EQUB. However if the parameter is a string
enclosed in double quotes it acts like EQUS. These can be mixed in the
same DB command which makes defining strings mixed with control codes
much easier. For example -
DB 7,"This is some text",10,13,"A new line",0
would be expanded to -
EQUB 7:EQUS"This is some text":EQUB 10:EQUB 13: EQUS"A new line":EQUB 0
As with DW and DD beware of allowing the line to become too long.
Again numbers beginning with a zero will be regarded as hexadecimal.
DB can be used with a multiplier to reserve an area of memory and set
it to any value. If a parameter begins with '*' then the following
number is taken as a multiplier and the number after that as the value
to be inserted. For example -
DB *100,32 (which could also be written as DB *100," " )
would reserve the next 100 bytes of memory as a data area and load them
with the value 32, a space character.
This can be mixed in with strings and single bytes and can be used
rather like SPC or STRING$ in Basic.
For example -
DB "1",*10,32,*8,".",*10,32,"First Menu Item",0
would be expanded to the zero terminated string -
1 ........ First Menu Item
One advantage of this is that the multiplier need not be an actual
number but could be an expression. This makes it a lot easier to change
the size of data areas or the length of strings by simply altering the
value of the variable.
If you just wish to reserve an area of memory and do not need it to be
set to any particular value then using a question mark as the value
after the multiplier will do so. For example
DB *100,?
would reserve 100 bytes but leave the area set to whatever random data
already existed there.
Page 39
Basic variables and DB
----------------------
It is possible to use variables instead of constants with DB. With the
Basic assembler you could use -
EQUD <var1> : EQUB <var2> : EQUB <var3>
so with SAsm you could use -
DB <var1>, <var2>, <var3>
You will notice that the previous examples using strings have shown an
immediate string enclosed in double quotes. With the Basic assembler it
is possible to use a Basic string variable with EQUS, eg.
EQUS version$
In earlier versions of SAsm this couldn't be done with DB but it is now
permitted. SAsm will recognise any variable ending in the '$' character
as a string so the 'DB variable$' will now equate to EQUS variable$.
You can also use string concatenation, eg.
DB prog_name$ + version$
DB prog_name$ + " Version "+version$
DB prog_name$ + STR$(version_number)
DB "A String"+CHR$(7)
although in the last case it would actually be neater to use -
DB "A String",7
For string concatenation to work with immediate strings the '+' must
IMMEDIATELY follow the closing quotes as in the above examples.
Immediate strings must be enclosed in double quotes. It would be
possible to modify SAsm to allow single quotes as in many other
assemblers but this would then make it impossible to permit this
character inside immediate strings.
SAsm will not recognise Basic strings defined with the '$' indirection
indicator. With the Basic assembler you could use -
EQUS $location%
which would use the cr terminated string at 'location%'. This won't
work using DB but it is so unlikely that it would be needed that I
don't regard this as a problem. There may be other combinations of
variables that won't work with DB, if you do have any problems please
tell me.
Page 40
ADRL
----
This is a two instruction 16 bit ADR directive. It takes the same
parameters as the normal ADR directive, that is the syntax is -
ADRL <register>,<location>
ADRL will always assemble two instructions when <location> is greater
then the current address. This is because the exact position of
<location> will not be determined until the second pass. However if
<location> is before the current address it's position will already be
known and so a single instruction will be assembled whenever possible.
If code length or speed is important you could use the ADR instruction
until you get an 'out of range' error to ensure that no superfluous
instructions are included.
Note that there MUST be a space between ADRL and <register> and that it
CAN now be made conditional
MOVL
----
This is a method of loading a large immediate number into a register. A
series of ADD or SUB instructions will be assembled to load the value.
The syntax is MOVL <register>,<number>. If <number> begins with a zero
it will be regarded as hexadecimal. <number> can of course be positive
or negative. If it is negative then MVN instructions may be used by the
macro but DO NOT adjust the number to allow for this as is required by
the normal MVN instruction. The macro will make all the adjustments
necessary so just write the actual number you require.
This macro is fairly simple and does not always produce the most
efficient code for loading a given value. If speed or code length is
paramount it may often be possible to reduce the number of operations
by hand coding.
Note that there MUST be a space between MOVL and <register> and that it
CAN now be made conditional
Page 41
DIV
---
This macro will perform a 32 bit integer division. The full syntax is;
DIV <dividend reg>,<divider reg>,<quotient reg>,<temp reg>
It therefore requires four DIFFERENT registers as its parameters and
you are responsible for loading the correct values into the registers
before using DIV. The results returned are;
<quotient reg> = <dividend reg> DIV <divider reg>
<dividend reg> = <dividend reg> MOD <divider reg>
The <temp reg> is used for working only and will be corrupted.
For example, to divide a number in R0 by a number in R1 and return the
result in R2 using R3 as temporary workspace use;
div r0,r1,r2,r3
On exit r1 will be unchanged and r0 will contain the remainder if the
number did not divide exactly.
Note that there MUST be a space between DIV and <register> and that
because it expands to a large section of code it CANNOT be made
conditional.
Note -
I have received 'complaints' informing me that DIV doesn't work and
just gives error messages. It does work perfectly. Most of these
complaints turned out to be from people who hadn't read (or hadn't
understood) the instructions. The parameters passed to DIV are the
numbers of the REGISTERS it will use NOT the actual numbers to be
divided. You are responsible for writing code to load the actual values
into these registers before using DIV to do the division. There is also
no error checking. If you try to do something silly like divide by zero
you could end up with your code either crashing or going into an
infinite loop.
If you want a 'general purpose' division routine then I suggest you
write a sub-routine (or expanded macro) which deals with all of these
things and uses DIV to do the actual work.
Page 42
-=O=- MACROS -=O=-
Sasm supports two types of Macros. Expanded Macros and Macro Functions.
There are advantages and disadvantages with each type. Both can be
included in your Macro Library.
Macro Functions - Pro/Con
-------------------------
These are normal Basic Functions and their use and format is fully
described in the 'Tutorial'. They have two disadvantages. Firstly
because they are Basic Functions you must include assembler brackets,
OPT setting, etc. and forward branches are awkward. Secondly it is not
possible to use any of the special features of SAsm such as local
labels, db, adrl, movl, etc. within a Macro Function. Also you cannot
call or define an Expanded Macro from within a Macro Function.
A serious disadvantage is that SAsm cannot recover from an error in a
Macro Function. Such errors are always Fatal and will produce an error
message giving a line number that does not exist in the file.
The first advantage is that this type of macro is not 'expanded' by the
pre processor so that no matter how many times you call it it doesn't
take any more memory. The second advantage is a consequence of this and
will only apply if you use a Macro Library without a hard disc. This is
because a Macro Function only appears once, at the end of the code, and
so only one disc access to load it from the Library will be required.
Expanded Macros - Pro/Con
-------------------------
These are short sections of code which are physically inserted into the
file each time the Macro is invoked. The big advantage with this method
is that you can use all the special features of SAsm, local labels,
etc. You can also call Macro Functions or other Expanded Macros from
within this type of macro.
Because Expanded Macros become part of the normal code SAsm can
normally recover from errors in them in the same way as it can recover
from most other errors.
The disadvantage is that an Expanded Macro must be defined before it is
used, although it can be defined in your Macro Library. Also as the
macro code is inserted into your source each time it is used more
memory is required although this unlikely to be a problem in practice.
Macro Names
-----------
Because Macro Functions and Expanded Macros are completely different
they can have the same name. You can even have Expanded Macros and
Macro Functions with the same name in your Library. SAsm will sort out
which to use.
Page 43
-=O=- EXPANDED MACROS -=O=-
An Expanded Macro must be defined before it is used. If you use a Macro
Library it may be defined there and SAsm will load it from the Library.
If you define a macro in your source file and one of the same name
exists in the Library then the macro in the source file will be used in
preference to the one in the Library.
Defining Macros
---------------
An expanded macro is defined as follows.
# SM <name>
........ \
........ > Normal SAsm code
........ /
# EM
and invoked by -
@ <name>
In each case <name> is the name given to the macro and, with any
parameters, is case sensitive. As with other SAsm directives the '#'
used by #SM (Start Macro) and #EM (End Macro) must be the first
non-space characters on the line.
The '@' character should be the first non-space character on the line
or, if the line starts with a label, the first non space character
after the label. There must not be ANYTHING on the line after the macro
call except a comment, which is defined in the usual way by preceding
it with ';' or '\'.
Whenever SAsm encounters a '@' it will match the following name with
any previously defined macros. When it finds one it will physically
insert a copy of the code into the file. If there are any LOCAL labels
in a macro they will be unique within that definition, but all
non-local labels will be global.
Macro Parameters
----------------
You can pass parameters of almost any type to an Expanded Macro. The
full syntax of the defining line of the start of a macro is -
# sm <name> <param name 1> , <param name 2> , <param name 3> ....
and of the calling line -
@ <name> <param value 1> , <param value 2> , <param value 3> ....
where <name> is the actual name given to the macro, <param name> is the
name given to each parameter and <param value> is the value that each
parameter will be assigned when the macro is expanded.
Page 44
A parameter is actually a Global Variable and should conform to the
variable type that Basic would use for the type of value that it will
hold. It can be an Integer, String or Floating Point variable. The
parameter passed must be suitable for that type of variable. It need
not be a constant value. Any expression which can be evaluated during
assembly to the correct type of variable may be used.
There must be at least one space between <name> and the first parameter
and parameters are separated by commas.
In fact you will recognise that the syntax has deliberately been made
identical to the way that parameters are passed to Basic Functions and
Procedures except that there are no brackets.
Local Labels in Expanded Macros
-------------------------------
You can use local labels in expanded macros and these should conform to
the syntax used elsewhere. You MUST start any local labels in a macro
definition with '00' to ensure that the labels used will be unique.
When the macro expansion ends the 'flow' of local labels in the main
code before the macro was used will be restored. A macro, with its own
set of local labels, can therefore exist within the area of 'normal'
local labels without confusion. In practical terms this simply means
that provided you ensure that any local labels used in a macro start
with '00' you can ignore the fact that a macro exists for the purposes
of local labels in the main code.
Similarly if expanded macros are 'nested' then any local labels defined
will be unique within that invocation and the labels in the 'calling'
macro will branch around labels in the called macro.
Remember that, like all non local labels, any other labels defined in
an expanded macro will become global and will assume the value assigned
in the current invocation.
Special features of Expanded macros
-----------------------------------
The most obvious advantage of expanded macros is that you can take
advantage of all the special features of SAsm when using them. The
ADRL, MOVL DB, DW and DD pseudo-ops can all be used if required.
You can call Macro Functions and other Expanded Macros can be invoked
from within macros. Expanded Macros can be 'nested' to a maximum depth
of twenty. In theory this could be greater but I couldn't think of any
possible (non-contrived) circumstance when I would need more than four
or five so I limited it to twenty.
Expanded Macros must NOT be invoked recursively. This would obviously
set up an infinite loop which would cause all available memory to be
filled. This is another reason for limiting the nesting of macros
because if this is done by accident an error will be flagged long
before this stage is reached.
Page 45
Example
-------
This is an example of how you could use a macro to print a string at
any location on the screen. Note that as usual I have used more spaces
than are actually necessary to make things clearer.
# SM print_tab x_pos , y_pos , display$
swi 256+31
swi 256+x_pos
swi 256+y_pos
swi OS_WriteS
equs display$
equb 0
align
# EM
The operation of the code should be obvious. Firstly there is the
equivalent of 'VDU 31, x_pos, y_pos' to position the text cursor where
required. OS_WriteS is then used to print the text which is placed in
memory immediately after it.
So, to print 'This is a test' at column 10, line 4 you would use
@ print_tab 10,4,"This is a test"
To illustrate nesting macros the following example splits this
procedure into two separate macros, one of which uses the other.
# SM do_tab x , y
swi 256+31
swi 256+x
swi 256+y
# EM
# SM print_tab x_pos , y_pos , display$
@ do_tab x_pos, y_pos
swi OS_WriteS
equs display$
equb 0
align
# EM
This would be used in exactly the same way as the previous example, but
note that as 'print_tab' uses 'do_tab' then 'do_tab' must be defined
before it can be used in 'print_tab'.
@ print_tab 10,4,"This is a test"
Would give the same results, and in this instance the code actually
assembled would be exactly the same.
Page 46
In fact, it could be split still more. Leaving the macro 'do_tab' as
previously defined;
# SM print_string string$
swi OS_WriteS
equs string$
equb 0
align
# EM
# SM print_tab x_pos , y_pos , display$
@ do_tab x_pos,y_pos
@ print_string display$
# EM
Once again exactly the same actual code would be assembled.
Errors in Expanded macros
-------------------------
SAsm will normally be able to recover from errors in expanded macros.
In this case the error message will be slightly different from normal
and in the form;
Error <error message> at line <number> in Macro <macro name> at line
<line number> in file <file name>
The line number in the file will be the line where the macro was
invoked. The line number within the macro will be the offset from the
start of the macro where the error occurred. If this was the invoking
line then the error will be shown as having occurred in line 0.
This can appear a bit strange if the macro invokes other macros. When
the error happens the macro has been expanded, so the line number may
be greater than the apparent size of the macro. For instance, in the
final example shown above if an error occurred in the line which
invoked 'print_string' in the macro 'print_tab' the error would be
shown as having occurred not at line 2, but at line 5.
This is not normally a problem is practice because the actual error can
usually be discovered by inspection but I may improve upon it in a
later version.
Page 47
-=O=- MACRO FUNCTIONS -=O=-
General
-------
Macro Functions are defined and used exactly as in the Basic assembler.
If you don't know how this works I refer you to the 'Tutorial'.
Briefly a Macro Function is a Basic Function who's definition, as with
functions in a normal Basic program, must appear after the #END
directive. You use it by simply writing FN<name>, where <name> is the
name of your function, in your assembler source. Most Macro Functions
will require parameters and these are passed by being enclosed in
brackets after the function name in the usual way.
You must remember when defining a Macro Function that when it is called
you have quit the assembler and are back in 'normal' Basic. As a macro
will probably include assembly code statements you will need to use the
square brackets and define the OPT setting to re-enter assembler.
SAsm uses two variables to define the OPT setting, Q% and PASS. You can
therefore use either of these when defining Macro Functions although I
suggest that you use PASS as its purpose is more obvious. The only time
you need to depart from this is if you are using a forward branch in
the macro. In this case you will need to define a two-pass loop within
the macro and so you MUST define your own OPT variable. In theory you
could modify PASS because although it is set by SAsm at the beginning
of each assembler pass it is not actually used, but it is probably
safer to use an independent variable. However it is very important that
you do NOT modify in any way the Basic Integer variable Q%.
WARNING - You cannot use the SAsm 'extra' mnemonics DB, DW, DD, DIV,
ADRL, MOVL or the enhanced immediate 2nd operands in Functions. These
are ONLY available in the main body of the code or within Expanded
Macros before the #END directive. You can call functions FNadr, FNmov,
FNdiv and FNset as alternatives if required. These will be retained in
later versions for this purpose.
These restrictions will not be removed in later versions of SAsm since
whenever possible you are advised to use Expanded Macros instead.
The Built-In Functions
----------------------
SAsm has a number of pre-defined Macro Functions and the following
section describes them. Do not to use them in new work except when
called from within other Macro Functions as the extra mnemonics ADRL,
MOVL, DIV, DB, DW and DD should be used instead.
As well as the functions described there are two others FNadrc and
FNmovc. These should not be used directly and so are not documented but
do not create your own functions with these names or conditional ADRL
and MOVL will not work correctly.
NOTE - The old functions FNdb, FNdw and FNdd have now been deleted.
Page 48
FNgap ( <size> )
----------------
Defines a gap in the code for use as a data area of <size> bytes. The
memory is not pre set to any value. If <size> is not exactly divisible
by 4 and you intend to follow FNgap with an opcode you should use ALIGN
to ensure that further assembly occurs on a word boundry. Use 'DB' for
preference unless within a Macro Function.
FNset ( <size>,<value> )
------------------------
Similar to FNgap except that the memory is preset to <value>. Use the
DB mnemonic in preference wherever possible.
FNadr ( <register>,<location> )
-------------------------------
FNadr is an expansion of the ADR pseudo-opcode. Its syntax is the same
except that the parameters must be enclosed in brackets. It can reach
any byte within 64K or within 256K if <location> falls on a word
boundry. If <location> is a forward reference FNadr always assembles
two instruction. If a backward reference FNadr assembles a single
instruction if possible and two only if absolutely necessary.
This is equivalent to the ADRL expanded mnemonic which should be used
in preference.
FNmov ( <register>,<value> )
----------------------------
This is an expansion of the MOV opcode to load a register with an
immediate value. Unlike the normal MOV this will generate sufficient
ADD opcodes after the initial MOV to load any 32 bit number. If <value>
is a negative number then MVN and SUB will be used. Note that when
using negative numbers you do not need to subtract 1 as you do with
MVN. eg. to load r3 with -123456 just use FNmov (3,-123456)
Use the MOVL mnemonic for preference unless within a Macro Function.
Page 49
-=O=- THE MACRO LIBRARY -=O=-
--** This facility is available only to REGISTERED users **--
Using the Macro Library
-----------------------
The Registered version of SAsm can record every Macro Function or
Expanded Macro call in your source file.
If it is an Expanded Macro and it has not been previously defined
somewhere in your code then it can be loaded from a special Library
file and inserted in the source.
If it is a Macro Function it will be checked against the definitions
found after the #END directive. If one or more definitions cannot be
found it will try to load the missing definitions from a Library file.
For Macro Functions the Library is only checked after all the source
files have been loaded so a Macro Function in a source file will
'override' a macro of the same name in the Library.
If an Expanded Macro is defined in the source file it will be used in
preference to one of the same name in the Library. If a macro is
defined part way through the source files then any calls to that macro
before it is defined will be loaded from the Library and those after
will use the version in the source file.
The 'L' parameter
-----------------
If you are using a hard disc this operation is so fast that the only
way you know it is happening is that SAsm will tell you that it is
loading Macro Functions or that the Library isn't required. If you are
using a single floppy drive you may have your Library file on another
disc. When you know that no Library macros are required it is annoying
to have to change discs and allow SAsm to satisfy itself that the
(probably misspelt) missing Macro isn't in the Library. You can
therefore add the suffix 'L' to your command line to tell SAsm NOT to
use the Library, even if SAsm$Lib (see later) is defined.
Page 50
Use of the 'V' parameter
------------------------
If you have used the 'V' (verbose) parameter then as each Expanded
Macro is being searched for a message is displayed. Normally this takes
the form -
Searching Library for Macro <macro name> - Loaded
But if the macro cannot be found in the Library it will say -
Searching Library for Macro <macro name> - Not found in Library
At this stage a missing macro will not be classed as an error but it
will become one during assembly because the macro will be missing.
The SAsm$Lib OS variable
------------------------
To tell SAsm that a Library exists you should either create an OS
variable 'SAsm$Lib' with the path/file name of the Library or use the
#LIB directive within the source file. To use the SAsm$Lib variable
type at the OS '*' prompt 'Set SAsm$Lib <filename>' where <filename> is
the path/file name of your Macro Library or put this command in your
!Boot file. You can of course have more than one Macro Library and just
change SAsm$Lib to refer to the one in current use.
When SAsm can't find a macro definition in the source files it has
loaded it will check to see if a Library has been defined. If it is it
will extract the 'index' which MakeLib has created. This will be
checked against any missing definition and if these appear in the
Library they will be included.
If SAsm can't find the definition of a macro in the source files and
the 'L' parameter hasn't been used but a Library hasn't been defined
then an Error message will be displayed. If you are sure that all the
required macros exist in the source it is best to use the 'L' parameter
to ensure that this doesn't happen.
Page 51
Preparing a Macro Library
-------------------------
First create a source file of Macro Functions and/or Expanded Macros.
These are macro definitions definitions exactly like the ones you would
normally use in your source files.
Each Expanded Macro should begin with the #SM directive and end with
the #EM directive.
In earlier versions of SAsm it was stated that each Macro Function
definition should end with an '=' as the first character on a line but
this is no longer required.
On your program disc you will find an application called 'MakeLib'.
Copy this to a blank disc and *MOUNT the disc or copy it to the Library
directory of your hard disc. Now at the OS '*' prompt type;
*MakeLib <source filename> <Library filename>
where <source filename> is the full path/file name of your Macro
definition file and <Library filename> is the path/file name that you
wish to call the actual Library file that SAsm will use.
MakeLib will load your Macro source file and prepare it for use by
SAsm. Once MakeLib has created the Library file the original source is
no longer required but you should of course keep it so that you can add
new macros and update your Library in the future.
The present version of MakeLib can only accept a single source file but
I intend to improve it to accept wildcards in a similar manner to SAsm.
Length of Library file
----------------------
The source for your Library file can be any length and can have as many
comments ay you like. As with normal SAsm source files these will all
be stripped before the routines are added to the actual Library.
The Library file can hold about 200 Macro definitions which should be
enough for anyone. I suggest that in practice you only put the macros
you frequently require in your Library and use INCLUDE files for those
only rarely needed. This will make the search time shorter and also
probably allow you to put your Library on your normal working disc if
you are using a single floppy.
Page 52
-=O=- SASM AND THE DESKTOP -=O=-
SAsm was originally intended to be used at the OS command line prompt.
However the introduction of good text editors such as !Zap and other
tools now make it possible to to develop programs within the Archimedes
desktop. Although SAsm is still not integrated into the desktop
environment Versions after 1.40 have features which help them to be
used in this way.
The new features
----------------
The changes which have been introduced are described in the section on
directives. They enable all of the parameters which previously had to
be typed at the command line (and more) to be inluded in the file as
Directives. This should mean that only the name of a single 'make' file
needs to be typed and this file can contain all other data needed to
assemble the program. The next step is to write a desktop 'front end'
for SAsm which will enable programs to be assembled within the desktop
in a similar manner to Acorns (unbelievably expensive) DDE and this
will be appearing soon (I hope!).
Even without the 'front end' you can now use SAsm within the desktop
very easily and assemble projects by clicking on a single 'Obey' file.
You will not now need to set the CSD as you will be able to use the
<Obey$Dir> OS variable to define the 'start point' of your project
directory structure.
Using SAsm from the Desktop
---------------------------
You can now include everything needed to assemble an extensive project
in a single short 'make' file. This would normally be a text file and
will contain all the preliminary directives (org, size, type, etc) plus
directives to define the object and error filenames and the library to
be used. Following these will come a list of Include files to be
assembled.
The main advantage of this system for desktop use is that it enables an
Obey file to run SAsm. For example, to assemble a desktop project you
should set up a directory structure as shown.
root
|
|
----------------------------
| |
source !app
The 'root' directory would contain your 'make' file and the Obey file
which will run it. It need not, of course, be the actual root directory
of a disc, it is just the root directory of your project. The !App
directory will be the RiscOS application directory for your project.
The 'Source' directory will contain all of your source files. You
could, of course, also have other directories to hold special library
files, error files, notes, etc. if required.
Page 53
Assuming the Make file is simply called 'Make' the Obey file would
contain just two lines -
Set Project$Dir <Obey$Dir>
Sasm <Project$Dir>.Make
When you double-click on this file it will atomatically create an OS
variable 'Project$Dir (or whatever you want) and set it to 'Obey$Dir',
ie. to the 'root' directory of your project. It will then Run SAsm
(either from the RMA if you have loaded the Module version or from
disc) with the filename of the Make file.
The Make file should define the various parameters to assemble the
program using the <Project$Dir> variable. Alternatively you could set
the OS variable using the CLI directive from within the Make file. It
would also contain directives to define the error file, library and
object file, for example -
# errfile <Project$Dir>.err
# obj <Project$Dir>.!App.!Runimage
and the files to be assembled would be -
# include <Project$Dir>.source.first_*
# include <Project$Dir>.source.second_*
# include <Project$Dir>.source.third_*
or whatever they are called. Note that you can still use the
'descending trailing digits' wildcard to assemble the latest version.
Your Make file need not, of course, be in the 'root' directory, it
could be in the source directory if you prefer, (it is, technically,
just another source file).
If you don't have a hard disc you will probably prefer to have your
source files (and certainly the error file) on the RAM disc. As SAsm
doesn't create any temporary files you don't need much spare space.
To assemble a project in this way just double-click on the Obey file.
You will have to wait for the new 'front end' to have messages trapped
in a desktop window, at present they'll just appear in a Command
window.
You can, of course, use SAsm in a 'Task' window but this means you will
need to define directories and type filenames again. In fact this is
the way that I normally use it but I am accustomed to operating with
set directories. The biggest advantage of using a task Window is that
if SAsm does crash the Wimp will normally allow you to close the
window, thus killing the task. This is very useful when I'm using SAsm
for development work on SAsm where this can happen. A disadvantage of a
Task Window is that on ARM 2 machines it does slow up operation.
Page 54
-=O=- PROBLEMS and QUESTIONS -=O=-
At present SAsm is entirely Command Line driven and doesn't have a
desktop 'front end'. There is no reason why this can't be done, in fact
a P.D. version has already been written by Ainsley Pereira and you may
have found a copy of this with your copy of SAsm. As soon as I feel
that the 'core' program is stable I shall write one so that you can
work entirely within the desktop if you wish.
IMPORTANT
---------
I'm continually trying to improve SAsm. PLEASE tell me if you have any
problems, even if you haven't registered. It's only by acting on your
bug reports and suggestions that I can keep improving it.
Reporting and diagnosing problems
---------------------------------
Tell me which version of SAsm you are using. You may have experienced a
'bug' which has already been fixed. It can save me a lot of time trying
to reproduce an error which can't occur on a later version. Ideally
send the version of SAsm that you are using. I may no longer have a
copy of that version (there have been quite a few updates!)
Please send a copy of the source file(s) that caused the problem,
preferably all files not just the one that gave the error, plus any
error files generated or other information. Especially I need to know
exactly how the program failed, 'it wouldn't work with this' isn't very
helpful! If you use SAsm in a Task Window then if you can please 'Save'
the contents and include it. If you don't normally run SAsm from a Task
Window then if possible please do so that you can send me the file.
Try to create listing and error files. If SAsm produces an uncorrupted
listing file it indicates the problem isn't in preprocessing. This
doesn't mean that something in preprocessing isn't causing a problem
for the assembler, but it does indicate that any problem will probably
be easy to spot and solve. Sometimes SAsm will produce a valid listing
or error file but it's type will be Data and not Text. Once again this
is a valuable pointer to the likely source of the problem.
You may find you can produce a perfectly good listing file by using a
'null' object filename (~) even though you can't get an object file. If
you can do this you may be able to examine it and discover the problem.
You may feel that all this isn't necessary because I should be able to
reproduce the problems that you have experienced. Unfortunately this
may not be so. I have sometimes been sent source code which assembled
perfectly when I tried it. On one occaision it wouldn't work on the
users machine because he was trying to run it in a P.D. Task Window
program using RiscOS 2 and it was the Task Window that was crashing,
not SAsm. There was no way that I could have reproduced this except
that the user enclosed a screen 'grabbed' from the desktop and I
recognised the non standard window.
Page 55
I use SAsm a lot myself and so it -*should*- be bug free because it
gets a lot of testing, not least because I use it to assemble SAsm
itself. However like most programmers I write code in a fairly
consistent way and to a regular format. I use some features a lot, some
rarely and others almost never. Experience has shown that there is
always someone who does something that I have never thought of. Often
this is quite legitimate, sometimes downright weird, but it just
introduces a variation that I haven't allowed for. Most modifications
to SAsm consist of 'fixes' and improvements to accommodate the way that
other people write code.
One possibility that can happen with both SAsm and the Basic asembler
is that labels, constants and register names are all 'normal' global
variables. Most assemblers, such as Acorns AAsm, treat register names,
labels and constants differently. You must therefore be careful not to
use the same name for more than one item. It is very easy to define a
label and a register or an offset into a data area with the same name
and disastrous consequences.
You may find that with a complex program it is best to use some sort of
prefix or suffix for data offsets and registers. Using names like r_ptr
for a register and d_offset for a data area offset will avoid this sort
of problem. Another solution is to use upper case names (beware the
SAsm reserved variables) or names beginning with a capital letter for
constants. As most constants will be integers a good solution is to
make them all Basic integer variables by ending the name with % because
'number' and 'number%' are different variables. No doubt you will
devise your own method of sorting the various names into easily
identified categories.
If you suspect that this might be the trouble then list out all your
labels to a file and check them against register names and constants.
That's why this function was included and it can save a lot of time.
If all else fails there is one final thing you can try. The registered
version of SAsm can save the fully processed data as a file before
assembly. You can do this either by using a 'p' parameter at the
command line or, instead of simply pressing RETURN when you type the
command, hold down both SHIFT keys and press the keypad ENTER. This
will stop any assembly taking place and will save the whole file with
whatever you had assigned as the object filename.
This function was included for my own purposes when debugging SAsm
itself. The resulting file is difficult to understand but it may help
you (or me) to discover what is happening.
Page 56
Speed of operation
------------------
The two questions I am most often asked about SAsm are 'what language
is it written in?' and 'how fast is it?'.
These can most easily be answered together. SAsm is written in machine
code using SAsm. Each version is assembled using the previous version.
The source code is then changed to take advantage of any new features
and re-assembled. I therefore test SAsm by 'self assembling' the
distributed version.
The source for SAsm consists of more than 7000 lines split over eight
files. These are loaded from disc, assembled, and the source file saved
to disc in less than seven seconds on an A440 with an ARM 2 processor
and an ST506 hard disc or about three seconds on an A5000. These times
assume operation direct from the CLI and are slightly longer if a Task
window is used. I think this is fast enough for most purposes.
Naturally if you didn't have a hard disc the time taken would be quite
a bit longer but as SAsm can easily use a RAM disc this shouldn't be a
serious problem unless you are trying to write long programs on a 1Mb
machine. Unlike most assemblers and compilers SAsm doesn't use much
memory for its own purposes.
Memory usage
------------
SAsm does not use any Heap or WimpSlot calls. It works with whatever
memory you have chosen to give it by way of the 'Next' slider on the
Task Display. I don't intend to change this in the CLI driven program
because I feel that this is something that should be under the
operators control. If you are writing machine code you are not a novice
user and should be capable of managing such things.
Whichever version of SAsm you are using the SAsm application code
itself will be located at &8000. After the application code space is
allocated for data areas used by SAsm. A 16K 'buffer' is then allowed
and the first file is loaded above this space. This will probably be
about 50K above the start of the 'slot' at &8000 and this is the only
RAM normally used by SAsm. As the file is processed it is copied down
to the start of this buffer. Obviously the 'tail' of the processed file
will eventually overlay the beginning of the 'raw' file, but this is
not of any consequence. When the first file has been processed a new
16K buffer is allocated after its end and the next file is loaded and
processed. This continues until all the files are completed.
With smaller programs this is then passed to Basic in this form for
assembly. However Basic can't cope with untokenised programs in excess
of about 6500 lines, so anything larger than this must be tokenised by
SAsm. If this is necessary you will see a message to this effect.
Page 57
Some notes on Local Labels
--------------------------
I shall describe briefly how SAsm handles local labels as is is
possible, although unlikely, for it to conflict with other variables.
You will be aware that Basic does not permit variable names to begin
with a number. SAsm therefore adds a two letter prefix to each local
label. This is given a wide spread to speed up access by Basic. The
prefix starts at 'zz' and reduces to 'Az', then 'zy' to 'Ay' etc. The
label prefix is reset each time a '00' label is encountered. You can
see exactly how this works by examining any Listing file where local
labels have been used. Where local labels are used in expanded macros a
similar method is used but with a three character prefix.
The system is simple and is designed to be very fast for Basic to use.
However it is possible for conflicts to exist if you have defined a
label or other variable in this form, eg. a variable 'xy10' could cause
problems. To avoid this you are strongly advised to ensure that your
own variables and labels don't use this form, eg. 'xy_10' couldn't
possibly cause a problem.
The most common problems
------------------------
There are a few 'features' of SAsm which can cause trouble. Some are
minor bugs that are not important once you know about them and will be
fixed when I have time. Others are errors which can occur because of
changes in the syntax used by SAsm. I will record some of the queries
which have been raised by users in the hope that it will avoid others
experiencing the same problems.
Before you decide that it's a bug in SAsm that's making things go wrong
PLEASE read through these and assure yourself that none of them could
possibly apply. Most of the 'problem code' that I am sent displays one
or more of these errors.
Because of the way in which SAsm operates it does not have perfect
control over assembly and there will always be things which can make it
crash. As time goes on these are slowly being eliminated and the error
trapping is being improved so that things which could cause a crash or
a 'lock up' in earlier versions are now either accepted or just give an
error message.
1. There MUST be a space between the mnemonic and the first operand for
many of SAsm's functions to work. This is not always essential with
the Basic assembler but it is good practice so I make no apologies.
2. MOVL, ADRL and DIV are actually macro's and not assembler mnemonics.
ADRL and MOVL can be made conditional but because DIV expands to
many lines of code with internal compare instructions it cannot.
3. Make sure that you start every set of local labels with '00'.
Page 58
4. You cannot use local labels, DB, DW, DD, ADRL, MOVL, DIV or any of
the enhanced second operator functions after the #END directive.
This means you can't use them within Macro Functions. You can,
however, use them within Expanded Macros because these are defined
before the #END statement.
5. Because DB, DW and DD instructions may expand considerably they can
cause a 'line too long' error if you put too much on one line.
6. SAsm removes redundant spaces and comments as it processes a file
but other operations expand it. Normally the contraction is greater
than the expansion so the file shrinks. As each file is loaded a 16K
'overhead' is allowed in case the file does grow. Normally this is
plenty but in extreme cases of large individual files without spare
spaces or comments the program could crash. I will add routines to
guard against this when I get time but I do not regard it as a
serious fault because a major aim of SAsm is to let you split up and
spread out your source files.
7. SAsm regards a ';' as defining a comment so if you insert a line of
Basic which has a PRINT statement that includes the ';' character
with a preceding space it will be 'cut off'.
8. There must be a CR or LF at the end of the last line of each file.
Check this by loading the file into your editor and pressing
CTRL-Down Arrow to move the cursor or caret to the end of the file.
It should be on a blank line below the last line. If it appears at
the end of the last line there isn't a final terminator and you'll
have problems.
9. SAsm can abort with an error if there is not enought space for line
numbers. This is because after SAsm has finished with the files
Basic will need to add 3 bytes to each line for the line number and
length byte. The solution is to make more memory available.
10. SAsm can quit with a fatal error giving a line number much greater
than the length of the file where the error occurred. Usually this
means that the error happened inside a Macro Function. This is
always a problem with Basic Functions and Procedures and there is no
simple solution. Often the only way of discovering the actual error
is to examine every FN call in the file in which the error occurred.
The filename given will be the name of the file from which the
function was called, and if the function is used elsewhere the most
probable cause is an error in one of the parameters passed. If it
persists you could try splitting up the offending file into smaller
sections to help you to 'zero in' on the problem.
Page 59
11. If SAsm 'crashes' for any reason (it can happen, although the things
causing it are slowly being eliminated) then it can leave the error
or x-ref file open. Normally if there is a fatal error these files
are closed but obviously if SAsm itself crashes this may not happen.
You are unlikely to be aware of this until you try to run SAsm again
when the 'file open' error will occur as SAsm tries to open an error
file which is already open. IN THEORY you should just get a 'beep'
and a warning message telling you that the error file was open and
assembly will proceed. (If this does happen then you will actually
have lost the first error message although the error will have been
counted). Source or Object files cannot be left open because these
are only accessed as whole files. The error could occur with a
listing file but this is unlikely. It is possible that some filing
systems may not return the 'standard' error number and so this error
won't be intercepted. In this case the program will go into an
infinite loop because every time it tries to report the 'file open'
error it will generate ...... a file open error! If this happens
when you are using a Task Window try pressing F12 and typing 'SHUT'.
12. The parameters passed to the DIV macro are the register numbers it
will use, not the values operated upon. You are responsible for
loading the values into the respective registers before using the
macro. Don't forget that these registers will be altered afterwards.
This macro has no error checking. If you try to divide by zero or do
something else stupid it may crash or go into an infinite loop. It
works well, but it's dumb, so it's up to you to use it properly.
13. SAsm does not mind whether you use LF (ascii 10) or CR (ascii 13)
characters at the end of each line. Most Archimedes text editors use
LF's but some, such as StrongEd, can use either or even a LF/CR
combination as is used on PC's. SAsm will not work with a LF/CR or
CR/LF combination. All textural output from SAsm such as Listing and
Error files conforms to the standard Archimedes format of a LF
terminating each line.
14. If assembly appears to stop part way through the code check that you
haven't put an #END directive before the real end. This can happen
if you re-arrange the order of the files or if the last file is
loaded out of sequence.
15. Check that wildcarded filenames only apply to one file or you will
get some files assembled twice! This can cause the previous error.
16 If you have a data area and the first 'instruction' immediately
following this is ADRL then you MUST ensure that the end of the data
area is ALIGN'ed. Otherwise the address might be calculated from an
'odd' base which will introduce errors.
17 The Basic Tokenising routine is NOT comprehensive. It should cope
with all simple Basic constructs of the type likely to be used in an
assembler source file. In theory it should distinguish between AND
and EOR when used as mnemonics or as operators. If in doubt use the
lower case versions of the mnemonics.
Page 60
-=O=- RELEASE HISTORY -=O=-
1.0 Oct. 91 First release
1.1 Nov. 91 Functionally as 1.0
Bug fixes
X-ref and Macro Library functions re-written
1.2 Nov. 91 Bug fixes
Much improved error handling
INCLUDE directive added
1.21 Jan 92 Restrictions on INCLUDE directive with
Shareware version removed.
1.22 Mar 92 Improved error handler
1.23 May 92 Minor bug fixes
1.24 June 92 Line numbering system rewritten, dramatic
speed increase for large files
Line number space relocation added
1.25 July 92 adrl, movl, div, db, dw, dd, added
Enhanced immediate 2nd operand
1.26 Feb 93 Bug in adrl in some examples of 1.25 fixed.
No public release of this version.
1.30 Mar 93 Expanded macros introduced.
db *xx,? to reserve area without setting
New Makelib tool for expanded macros
Module provided so SAsm can now be run from
the RMA for floppy disc users.
1.31 Apr 93 ADRL and MOVL can be conditional
1.32 Jun 93 Bug fixed in expanded macro stack.
1.41 Aug 93 #obj, #lib, #errfile, #cli, #verbose, #quiet,
#xref and #noxref directives introduced.
Tab characters accepted as delimiters.
1.42 Sep 93 Bug with DB, DD and DW in upper case fixed.
Bug with comment on Macro call line fixed.
'Line Too Long' trapped during preprocessing
1.43 Dec 93 Expanded macro call permitted after label
Minor bug fixes
1.44 Dec 93 #enhance and #noenhance directives introduced
1.45 Dec 93 Bug in macro call with no params fixed
Page 61
1.46 Dec 93 'P' parameter introduced
#insert directive introduced
1.50 Jan 94 x-ref list to file
x-ref bug fix with label same as opcode
Assembler listing file
Added short help text
SWI name processing
Local labels with LDR and STR
String variables accepted by DB
'Q' switch added to quit before assembly
'N' switch added to list label names
#LABELFILE to send labels to file
1.51 Mar 94 Minor bug in #SWION fixed
reg! permitted without space for LDM/STM
More improvements to error trapping
DIV now included in unregistered version
1.52 Mar 94 Filetypes Module and Utility don't need ORG
Bug with obj filename starting with '!' fixed
Added 'demo' application
1.53 Mar 94 Labels now listed alpahbetically, not reverse
FNdb, FNdd, FNdw removed
#AREA directive introduced
Descriptive text between { and } allowed
OSET variable implemented
Bug in trapping open Error File error fixed
1.54 Apr 94 Basic tokenising introduced with large files
Corrected bug with ':' in INCLUDE filenames
Registration Form for SAsm
Please complete this and post it with your cheque for Eight Pounds to;
David Holden, 39 Knighton Park Road, Sydenham, London SE26 5RN
____________________________________________________________________
Name and Address:
____________________________________________________________________
Where did you obtain SAsm:
____________________________________________________________________
Have you had any problems:
____________________________________________________________________
What additional features would you like: