ASM11
A
two-pass absolute macro cross-assembler for the 68HC11
ASM11 - Copyright © 1998-2011 by Tony Papadimitriou <tonyp@acm.org>
ASM11
[-option [...]] [[@]filespec [...]] [>errfile]
·
option(s)
may appear before, in between or after filespec(s).
·
option(s)
specified apply to all files assembled, regardless of command line placement.
·
Text file(s) containing list(s) of files
to be processed may be specified by naming the text file on the command line,
prefixed with a «@» character. These
text files may not contain command line options.
·
filespec(s)
may include wildcard characters (?,*).
Wildcards are not allowed in filespec(s)
that are prefixed with a «@» but are allowed in filespecs inside @files.
·
If the file extension for a source filespec
is omitted, the extension «.ASM» is assumed (see description of the –R.ext
option below).
·
Assembler errors may be redirected to errfile
using standard DOS output redirection syntax.
This capability may be used in conjunction with, or as an alternative to
the –E+
option.
·
Any label can hold a
value that is 32-bit long. Even though
the CPU cannot understand numbers larger than 16-bit for data or addressing,
the ability to have 32-bit labels allows keeping constants that are larger than
16-bit for use in later constant calculations.
Decimal numbers are signed; the largest number is
+/-2147483647. Hex or binary numbers
are unsigned and can go up to the full 32-bit value (2^32-1). For
example, a symbol holding the crystal frequency of operation can be expressed
with Hz detail to be used later to derive other constant values (such as
cycle-based delays). The 32-bit capability is NOT available in the DOS
version.
·
The assembler will set the DOS ERRORLEVEL
variable when it terminates as indicated:
0 No error, assembly of last file
was successful
1 System error (hardware I/O
failure, out of disk space, etc.), or -W
option failure
2 Error(s) generated (or Escape
pressed) during assembly of last file
3 Warning(s) generated during
assembly of last file
4 Assembler was not started
(help screen displayed, -W
option used with success)
1. No file(s) found
Option |
Default |
Description |
|
|
|
|
|
-C[±] |
-C- |
Label case sensitivity: + = case
sensitive (See also #CASEON/#CASEOFF) |
|
-Dlabel [:expr] |
|
Use up to ten times to define symbols
either for conditional assembly (e.g., IFDEF,
IFNDEF, and IF directives) or
normal use. Symbols are always
uppercase (regardless of -C option). If they
are not followed by a value (or expression) they assume the value zero. Expression is limited to 19
characters. Character constants
should not contain spaces, and they are converted to uppercase. Cannot be saved with -W. |
|
-E[±] |
-E- |
Generate *.ERR file (one for each file
assembled). *.ERR files are not
generated for file(s) that do not contain errors. |
|
-EH[±] |
-EH+ |
If –E+ is in effect, hide (do not display) error messages on
screen. |
|
-EXP[±] |
-EXP- |
When on, an .EXP file is created
containing all symbols defined with an EXP rather than an EQU pseudo-opcode. The resulting file can then be used as an #INCLUDE file for other
programs. This allows for automatic
creation of include files with exported global symbols. |
|
-FD[±] |
-FD- |
When on, the assembler uses a fake/fixed
date (specifically, Jan 1, 2011) for the internal symbols :YEAR, :MONTH, and :DATE. It does not
falsify the date shown on the listing header, however. This option is useful to let you always get the same S19
CRC value (shown both at the end of the listing file, and on the command-line
next to each successfully assembled file), even if you use the :YEAR, :MONTH, and :DATE internal symbols in your source code, which based on the
compilation date of your program would normally alter the resulting S19
CRC. This would, in turn, make it
more difficult to quickly check if your program produces the same, or a
different binary, since last time you checked. Keeping a record in your source of the most recent S19 CRC
produced with the –FD option, let’s you know if something has (perhaps,
inadvertedly) changed. Without the –FD option, you can’t be sure if it’s just the date that
changed, or something else. WARNING: Do NOT include this option in batch or
makefiles that compile your programs automatically, or you risk producing
consistently mis-dated firmware. It
should only be used for manual verification purposes. It’s not by accident this option cannot be saved with the –W switch. |
|
-Ix |
|
Define default INCLUDE
directory root. Relative path files
not found relative to the main file, will be tried next relative to this
directory. This switch does not
affect absolute path file definitions.
Affects both the INCLUDE and the IF(N)EXISTS directives. |
|
-L[±] |
-L+ |
Create a *.LST file (one for each file
assembled). |
|
-LC[±] |
-LC+ |
List any conditional directives fully
(the directives only, not the contents in between), even when they are
False. This is the new behavior of
ASM11 as of v1.81 but the option is there for those few that liked the old
way. |
|
-LS[±] |
-LS- |
Create a *.SYM symbol list (one for each
file assembled). May be useful for
debuggers that do not support the P&E map file format. |
|
-LSx |
-LSS |
x may be either S
(default) for simple SYM file, E for EM11/Shadow11
SYM format, or N for NoICE SYM format. |
|
-M[±] |
-M+ |
Create a *.MAP (one for each file
assembled). *.MAP files created may
be used with debuggers that support the P&E source-level map file format. |
|
-MTx |
-MTP |
Specifies type of MAP file to be
generated (if –M+
in effect): -MTA : Generate parsable
ASCII map file -MTP : Generate
P&E-style map file |
|
-O[±] |
-O+ |
Enables these three warnings: ‘S19 overlap’, ‘Violation of MEMORY
directive’, and ‘Violation of VARIABLE directive’. |
|
-P[±] |
-P+ |
When on it tells the assembler to stop
after Pass 1 if there were any errors.
Provides for faster overall assembly process and less confusion by
irrelevant side errors of Pass 2.
Warnings alone never stop in Pass 1. |
|
-Q[±] |
-Q- |
Specifies quiet run (no output) when
redirecting to an error file (DOS only).
Useful for IDEs that call ASM11 and don’t want to have their display
messed up. Beginning with v2.07, this option can also be used to
suppress all output from #Message directives. |
|
-Rn |
-R74 |
Specifies maximum length of S-record
files. The length count n includes all
characters in an S-record, including the leading «S» and record type, but not
the CR/LF line terminator. Minimum
value is 12 (for one object byte per record) while maximum is 250 (120 object
bytes per record). |
|
-R.ext |
-R.ASM |
Specifies the default extension to
assume for source files specified on the command line, which do not directly
specify an extension. |
|
-REL[±] |
-REL+ |
Allows generation of «BRA/BSR
instead of JMP/JSR» optimization warnings when enabled. (See also OPTRELON/OPTRELOFF) |
|
-RTS[±] |
-RTS- |
Allows generation of «JSR
followed by RTS» subroutine call optimization warnings when enabled. (See
also OPTRTSON/OPTRTSOFF) |
|
-S[±] |
-S+ |
Generate *.S19 object file (one for each
file assembled). |
|
-SH[±] |
-SH- |
Include dummy «S0» record (header) in
object file (only if –S+). |
|
-S9[±] |
-S9+ |
This option can be used to turn off
generation of the final S9 record found by default in all S19 files. This may be useful when assembling code in
parts that will be combined with other S19 files. Since you only need a single S9 record in the final S19 file,
you can use this option to not produce S9 records for all but one of the
files that will be merged together to produce a single object file with a
single S9 record. This option cannot
be saved with the –W switch. Example: Application and bootloader merging. Assuming you merge the first with the
second (in that order), the bootloader should be assembled as usual, and the
application with the –S9 option in effect. |
|
-SP[±] |
-SP- |
When
enabled, the operand part of an instruction is stripped of spaces before
parsing. In this case, possible
comments must begin with semi-colon.
(See also SPACESON/SPACESOFF) |
|
-T[±] |
-T- |
Makes
all errors look like Borland errors (useful to fool certain third-party
IDEs). |
|
-Tn |
-T8 |
Specifies
tab field width to use in *.LST files and object code strings. Tab characters embedded in the source
file are converted to spaces in the object code strings, and in the listing
file such that columns are aligned to 1 + every nth character. |
|
-Ux |
|
Define default OUTPUT directory. If this option is defined, all produced
files will end up in this directory, regardless of where the source file is
located. When this option is
undefined (no path given), produced files will end up in the same directory
as the primary source file. Not available in the DOS version. |
|
-X[±] |
-X+ |
Allow
recognition of extra, non-68HC11-standard mnemonics in source files. (See
also EXTRAON/EXTRAOFF) |
|
-WRN[±] |
-WRN+ |
Enables or disables the display of all
warnings. When enabled, only warnings
that aren’t disabled individually will be generated. When disabled, it
overrides local warning options (such as -REL
and -RTS). |
|
-W |
(none) |
Write options specified earlier on the
command line to the ASM11 executable (DOS), or ASM11.CFG (Win/Linux). The user-specified options become the
default values used by ASM11 in subsequent invocations. Filespec(s)
on the command line are ignored.
Assembly of source files does not take place if this option is
specified. |
Pseudo-Op |
Description |
|
|
|
|
[label] ALIGN expr |
Case
1. If no label is present, it aligns the current location counter to be a
multiple of the given expression. Case
2. If a label is present it aligns the value of that label to be a multiple
of the given expression. (In this
case, however, it does nothing to the current location counter.) It issues an error if the label is not
already defined. COMPATIBILITY ISSUE WITH VERSIONS PRIOR
TO 8.30: Prior
to version 8.30, the optional label would be assigned the current location
counter value after the alignment.
The label could not be defined earlier, or you would get an error. With
v8.30 and later, you get an error if the label is not already defined by the
time ALIGN is reached because the new behavior requires a previous
definition so it can align the existing value of the label. This makes it easy to catch all
incompatible ALIGN statements written for the previous version(s). If you get an error, simply move the label
after the ALIGN statement. |
|
DB string|expr[,...] |
Define
Byte(s). expr may be a constant numeric, a label reference, an
expression, or a string. DB encodes a single
byte in the object file at the current location counter for each expr encountered (using
the LSB of the result) or one byte for each character in strings. |
|
DS blocksize |
Define
Storage. The assembler’s location
counter is incremented by blocksize. Forward references not allowed. No code is generated. |
|
DW expr[,...] |
Define
Word(s). expr may be a constant numeric, a label or an expression. expr is always interpreted as a word (16-bit) quantity, and is
stored in the object file at the current location counter, high byte followed
by low byte. |
|
END [expr] |
Provided
for compatibility. The END directive
cannot be used to terminate assembly; ASM11 always processes the source file
to the end of file. If expr is specified, the
word result is encoded in the S9 record of the object file. |
ENDM
|
Ends
definition of a macro. |
|
label DEF expr |
Assigns
a DEFault value to a label.
In other words, this is a conditional EQU. It only assigns the label if the label is
currently undefined. LABEL
DEF EXPR is equivalent to: #IFNDEF
LABEL LABEL
EQU EXPR #ENDIF Note: The value that appears in the
listing file is the actual new value of the label, which may be different
from the value of the expression, since the assignment may not occur. |
|
label EQU expr |
Assigns
the value of expr
to label.
See also EXP and SET |
|
label EXP expr |
Assigns
the value of expr
to label. This is similar to EQU but with the
following difference: Labels defined thus will be included in the .EXP file
as regular SETs. This effectively allows exporting symbols for use from
other source files. It makes it possible
to give only object code to others along with the produced .EXP file so that
they can «link» the object to their source. Found in versions 1.84b+ but will
be honored only in 1.85+ |
|
FCB string|expr[,...] |
Form
Constant Byte(s). Same as DB. |
|
FCC string|expr[,...] |
Form
Constant Character(s). Same as DB. |
|
FCS string|expr[,...] |
Form
Constant String. Similar to FCC, but it
automatically adds a terminating null (0) byte to the end of the string
defined (for ASCIZ strings). |
|
FDB expr[,...] |
Form
Double Byte(s). Same as DW. |
|
LONG expr[,...] |
Form
32-bit long word(s). expr may be a constant
numeric, a label or an expression. expr is always
interpreted as a 32-bit quantity, and is stored in the object file at the
current location counter in big-endian order. Not available in the DOS version. |
|
MacroName MACRO comments ... REMACRO ... |
§
Parameters are passed during invocation in the
operand field separated by commas (or whatever delimiter you have defined
with the #PARMS directive, or the special one-time parameter
separator override.) §
To use a null parameter, just put two delimiters
next to each other (e.g., @MACRO PARM1,,PARM3). Note: This will work for any delimiter except
for space; two or more consecutive spaces – outside a string, of course – are
seen by the assembler as one space in the parameter field. Space delimiters can only be used with
sequential parameters without gaps in between (which is good for the
majority of cases, but not all).
If you must know, this is because the assembler trims multiple spaces
between fields to locate the operand field.
If spaces were allowed to separate null parameters, it would also have
to count the spaces from the macro name to the parameter field less one that
is required to separate the two fields and possibly less one more that could
be used with a “space” parameter override, and since the null parameters
could be first in the list of parameters, this would be very confusing, and
hard to get it to work correctly (especially since you can’t easily count
spaces) while also maintaining the desired code formatting. So, when calling a macro with non-trailing
null parameters, make sure the parameter separator is NOT a space (either by
default or by override), or you will get incorrect macro expansions
(and, depending on what the macro does and how it expands, you may not always
get side errors).
|
MERROR [text]
|
Combines
an #ERROR directive
followed immediately by an MEXIT, which is commonly found in macros. This can only be used inside macros. |
MEXIT [expr]
|
Causes
an unconditional early exit from a macro expansion. (Normally, used inside a conditional block.) If the optional expression (without any
forward references) is present, its value will be placed in the :MEXIT internal variable.
If the expression is missing, the current value of :MEXIT will not be changed, allowing for cascaded return values
from nested macros. |
MSUSPEND
MRESUME
|
MSUSPEND
can be used only from within a macro (usually once, but since there is no
limit, more than once, if needed) to temporarily suspend the execution of the
current macro. Suspending
a macro preserves the current macro state (parms, counters, etc.) just like
nested macros do to protect the parent macro’s state, but it allows for code
outside any macros to be assembled in place of the MSUSPEND
keyword, as if it were part of the macro (except that it is actually
assembled outside the macro, so none of the macro-only features can be used,
and none of the macro limitations apply – for example, normal use of #INCLUDE is possible, as well as definition of new macros, etc.) This
makes it much easier to create nestable macros that emulate block
structures, than by using two separate macros (one for block begin, and one
for block end) and trying to keep them synchronized. Note:
When a nested macro is suspended, all macros leading to the currently
executing macro are indirectly suspended as a side effect. MRESUME can be used only from outside
any macros to resume execution of the most recently suspended macro. You can have several macros in the
suspended state, but they can only be resumed in a LIFO order (i.e., stack
order). This allows for the creation
of nested blocks (like WHILE, FOR, IF, REPEAT, etc.) commonly found in
higher-level languages. The recursion limit (see #MLimit) counts suspended macros
also, because these are stacked just like when doing normal nested macro
calls. This MSUSPEND/MRESUME feature makes it
particularly easy to replace pairs of macros (like FOR … ENDFOR) that normally appear right
before and after a code section to create a block structure, with a single
macro that does all the required work and simply allows (via the use of the
keyword MSUSPEND)
the inclusion of any arbitrary code in between (i.e., between the macro call
and the MRESUME
keyword). Simple nested example (counts
lines of intermediate source code, and issues warning if optional limit is
exceeded): org
* CountLines macro [Limit][,Description] mset
2, ~@@~ #temp
:lineno+1 msuspend #temp
:lineno-:temp #Message
Section~2~ spans {:temp} lines
#ifnb ~1~ #if :temp > ~1~ #Warning
Too many lines (>{~1~}) #endif #endif endm ; To use: @CountLines ,OUTER nop @CountLines ,INNER nop nop mresume nop mresume |
MSTOP [#ALL#]
|
When used
inside a macro, it causes an unconditional early termination of all currently
executing macros, and regardless of nesting level. (Normally, used inside a conditional block.) When
used outside a macro, it causes the most recent suspended macro to stop being
suspended. When the optional #ALL# parameter is used, then all nested suspended macros are
stopped (become no longer suspended). |
MSTR index[,index]*
|
MSTR tests each one of the specified indexed macro parameter
text for being a string, and, if not a string, it changes it to one using the
appropriate delimiters based on the contents of the parameter text. It is equivalent to the following
sequence (but repeated for each specified index n): #IFPARM ~n.~
#IFNOSTR ~n.~
MSET n,\@~n.~\@
#ENDIF #ENDIF |
MSET index[,text]
MDEF index[,text]
MSWAP index,index
|
MSET changes the current macro’s index-ed parameter to the text that follows, or to null if no
text follows. There are many
potential uses for this capability (such as using the macro parameters as
temporary work text variables.) It is
particularly useful, however, with macro loops using the MTOP command. MDEF
is similar to MSET
but it only changes the text of the parameter if the parameter is currently
null. This is the same as using MSET within an #IFNOPARM conditional
block. It’s useful for setting
default macro parameters (normally, at the top of the macro). MSWAP
simply swaps the text of any two parameters.
(Swapping a parameter with itself has no effect.) As an example for MSWAP, in macros with
multiple single operands, you can use it to bring the working operand always
in, say, ~1~,
which may be simpler to use than the equivalent ~{:loop}.~ from inside a loop. Note: index is any expression that doesn’t contain forward references. |
MREQ ind[,ind]*[:errmsg]
|
Checks
each of the specified macro parameters (separated with commas) for null value
(empty). If the parameter is null, an
appropriate internal error message is displayed, and the macro expansion is
terminated at that point. If the optional errmsg parameter is present (which must follow a colon), this
error message will be displayed instead of the default error message. This can be used to specify which macro
parameters are required, and print an error message, if these parameters are
null. If more than one of the
specified parameters are null, the message will repeat for each one of them. You may use MREQ
multiple times, perhaps, once for each parameter, so that you can have a
unique error displayed for each parameter. Note: ind is any expression that doesn’t contain forward
references. errmsg is any text. If ind contains an internal variable (such as :LOOP), it must be
enclosed in { ... } because the colon is also used as the beginning of the errmsg. |
MTOP [limit expr]
|
Causes
an immediate unconditional jump to the top line of the current macro,
while incrementing the :LOOP counter. It can be
used either alone or within conditionals.
The advantage to using MTOP over @~0~ (a macro call to self) is that whatever parameters were
passed in the macro do not need to be specified again as the macro is never
exited. Also, no counters are
incremented, except for :LOOP. This means,
however, that $$$
based labels (which are unique to a macro invocation) are still in the
same scope as before the MTOP command since no new macro has been invoked. If the optional limiting expression
(containing only non-forward references) is present, its value will be
compared to the :LOOP
counter and MTOP
will execute only if the current value of :LOOP
is less than the value of the expression.
Example (shift word right one or more times): lsr.w macro Address[,Count] mdef 2,1 ;default
Count=1 lsr ~1~ ror ~1,~+1~,1~ mtop ~2~ endm As another example, an expression like
the one that follows can be used to loop while the next parameter is not
null: mtop :loop+:{:loop+1} |
MDO [start expr]
MLOOP [limit expr]
|
MDO and MLOOP work together to form a local DO ... LOOP inside
a macro. Note: MDO
and MLOOP cannot be nested because MLOOP
always matches the most recent MDO
of the current macro. MDO
simply marks the current line (i.e., the line containing the MDO keyword) as the beginning of a local
loop, and (re)initializes the :MLOOP counter to one (1), or to the value of the non-forward
expression, if one is present. MLOOP
causes an immediate unconditional jump to the line following the most
recent MDO
keyword, while incrementing the :MLOOP counter (not to be confused with the :MACROLOOP or :LOOP counter). If no MDO was used up to this point in the macro, MLOOP jumps to the top of
the current macro (just like MTOP would), but it only affects the :MLOOP counter (whereas MTOP only affects the :LOOP counter). If the optional limiting expression
(containing only non-forward references) is present, its value will be compared
to the :MLOOP
counter and MLOOP
will execute only if the current value of :MLOOP
is less than the value of the expression.
Example (multi-byte addition): add.m macro Op1,Op2,Ans[,Size] mdef 4,1 ;default
size = 1 #push #spauto :sp psha mdo lda ~1,~+{~4~-:mloop}~,1~ #if
:mloop = 1 add ~2,~+{~4~-:mloop}~,2~ #else adc ~2,~+{~4~-:mloop}~,2~ #endif sta ~3,~+{~4~-:mloop}~,3~ mloop ~4~ pula #pull endm As another example, an expression like
the one that follows can be used to loop while the next parameter is not
null: mloop :mloop+:{:mloop+1} |
|
label NEXP symbol[,expr] |
Assigns
the current value of symbol to label as if with EXP. Then, it
increments the value of symbol by one (as if with SET) or, if the optional expression is present, by the value
of that expression. Useful for
defining a series of symbols based on a common starting value. Note: symbol is a single label and not an expression. See also NEXT,
SETN |
|
label NEXT symbol[,expr] |
Assigns
the current value of symbol to label as if with EQU. Then, it
increments the value of symbol by one (as if with SET) or, if the optional expression is present, by the value
of that expression. Useful for
defining a series of symbols based on a common starting value. Note: symbol is a single label and not an expression. See also NEXP,
SETN |
|
ORG expr |
Sets
the assembler’s location counter for the active segment. Code generated after this directive will
be assembled starting at the location specified by expr. |
|
label PROC |
First,
it advances the @@ local label
counter, and then it assigns the value of the program counter (*) to label. This allows using
symbols locally for a specific section of code (e.g., a subroutine). The symbol to the left of PROC is always in the new
scope. Each time PROC (or #PROC) is encountered, the
assembler increments an internal 32-bit local symbol counter. Symbols containing @@ anywhere inside their name (except at
the very beginning) at least once (for example, Loop@@) will have the @@ part replaced with a special control
character (different from what is used with macro local $$$) and the current value of the internal
local symbol counter (similar to $$$ with macro local labels). Up until a PROC or #PROC is encountered in the program, the @@ is not treated specially (i.e., the @@ is not converted to a special
number). This makes this feature
compatible with code written prior to its introduction. The current value of the corresponding
internal counter can be found in the internal symbol :PROC See also #PROC |
|
RMB blocksize |
Reserve
Memory Byte(s). Same as DS. |
|
label SET expr |
Assigns
the value of expr
to label even if label is already defined
with a different value. This is similar to EQU but allows
making multiple re-definitions. The
value set will be used until another SET pseudo-instruction or to the
end of the assembly process. Warning:
Careless, or simply wrong use of this directive can lead to multiple side
errors or warnings (please note this is a two-pass assembler). Using a forward SET
defined symbol may lead to problems, as the value used will be the one from
the last SET definition, which is not necessarily the one we want. Correct behavior is guaranteed if any
symbols re-defined with SET are used only after each new re-definition, otherwise, the
first reference in Pass 2 will use the value from the last re-definition in
Pass 1. Example
of wrong use: 1. lda
#Value ;we expect 123, actual
is 234 2. Value equ 123 ... 3. lda
#Value ;we expect 234, actual
is 123 4. Value set 234 Value
in line 1 will be 234 (the last known value from Pass 1) while Value in line
3 will be 123 (most recent value in current Pass 2).
Example of correct
use:
1. Value equ 123 2. lda
#Value ;we expect 123, actual
is 123 ... 3. Value set 234 4. lda
#Value ;we expect 234, actual
is 234 See
also EXP and EQU
|
|
label SETN symbol[,expr] |
Assigns
the current value of symbol to label as if with SET. Then, it
increments the value of symbol by one (as if with SET) or, if the optional expression is present, by the value
of that expression. Useful for
(re-)defining a series of symbols based on a common starting value. Note: symbol is a single label and not an expression. See also NEXP,
NEXT |
Source File Processing
Directives
·
All processing directives must be prefixed
with a $
or #
character. ASM11 will recognize either
character as the start of a processing directive.
·
If a directive has a corresponding
command-line option, the directive in the source file will override the command
line directive at the point in which the source file directive is encountered.
·
[text] will
be trimmed of duplicate spaces. To have
more than one consecutive space display, use the Alt-255 character, as many
times as needed.
Directive |
Description |
|
|
|
|
#CASEOFF |
When
#CASEOFF
is in effect, all symbol references that follow are converted to uppercase
internally before they are searched for or placed in the symbol table. (Debug
and DEBUG are the same symbol.) Equivalent to the –C- command line option. |
|
#CASEON |
When
#CASEON
is in effect, symbol references are NOT internally converted to uppercase
before they are searched for or placed in the symbol table. (Debug and DEBUG are two different
symbols.) Equivalent to the –C+ command line option. |
|
#CRC expr |
The
two CRCs (user and S19) maintained by the assembler are 16-bit each, and they
are updated only during PASS2 by each produced user code/data byte that is
put into the S19 file. The starting
CRC value for both CRCs is zero. With this directive you can alter the
user CRC value at any time (either before the very first byte of code/data to
produce a different CRC for the same firmware, or several times in between to
skip certain volatile sections, for example). The computed CRCs are available by
accessing the internal symbols :CRC and :S19CRC The formula used for the 16-bit CRC
calculation is very simple to be easily implemented even in tiny bootloaders: 16BitCRC :=
16BitCRC + 16BitAddress*8BitData
:S19CRC is mostly useful with the END
directive (END
:S19CRC) as it is not affected by the #CRC
directive. An S19 loader can check
the overall integrity of the S19 file. :CRC, on the other hand, is mostly useful for checking code
after it has been loaded into the MCU, at each reset, for example. Please note that for both CRCs all $00 bytes do not affect the calculation
while, for the user CRC only (:CRC), all $FF bytes are intentionally skipped. This allows for the CRC in an S19 file
(which does not necessarily fill a contiguous block of memory) to match the
CRC computed by the MCU over a complete block of memory without the MCU
bootloader knowing in advance the actual addresses used within that block,
provided any unused bytes are in the erased state. As a side effect, however, any
$00->$FF or $FF->$00 alterations in the file cannot be detected with
the user CRC. |
|
#CYCLES [expr] |
First,
the optional expression is calculated using the current values of any
internal symbols. Then, the current value of :CYCLES is copied to :OCYCLES. Finally, the internal:CYCLES counter is set to
zero (if the optional expression is missing), or to any arbitrary value (the
result of the expression). This directive can also be used inside
macros to restore the cycle counter of surrounding code, if the macro cycles
should be counted in a special way, or not at all. |
|
#DATA |
Activation
of the DATA segment. Default starting
value is $103F (the CONFIG register). |
|
#DROP macro[,macro]* |
Undefines
one or more macros. If a macro is not
currently defined, a warning will be issued (to protect from possible typing
errors). To drop all macros (global and local)
with a single command, use * (asterisk) in place
of the macro name. There is no
warning if no macros found. To drop all local macros (for the
current file only) with a single command, use ?*
(question mark followed by asterisk) in place of the macro name. There is no warning if no local macros
found. If used from inside a macro, and that
macro is dropped, the macro will terminate at that point. The rest of the macro will not be
processed. The special macro named ? (just a single question-mark) is to be
used ad-hoc, and it is automatically dropped (without warning) at each new
redefinition. You may also drop it
with #DROP but only need
to do so if you want to force errors in later use of the macro, so you can
easily locate them. You cannot drop macros that are
currently active above the current macro level (e.g. nested macros leading to
current one.) |
|
#EEPROM |
Activation
of the EEPROM segment. Default
starting value is $B600. |
|
#EJECT |
See
#PAGE |
|
#ELSE |
When
used in conjunction with conditional assembly directives (#IF, #IF[N]DEF, $IF[N]Z, #IFMAIN, #IFINCLUDED, etc.), code following the #ELSE directive is assembled if the conditional it is paired
with evaluates to a not-true result. |
|
#ENDIF |
Marks
the end of a conditional-assembly block. Conditional assembly statements may be
nested if they are properly blocked with #ENDIF directives. |
|
#ERROR [text] |
When
encountered in the source, the assembler issues a error message in the same
form as internally-generated errors, using the text
specified, prefixed with «USER: » |
|
#EXIT [expr] |
If
no expression is present, it immediately exits the current #INCLUDE file. (Does nothing if used inside a main
file.) If the optional expression is present
(normally though, this might be just a single label), the exit occurs only if
the expression is defined (as if when checked with #IFDEF). This can be used in the top of #INCLUDE files, like so:
#EXIT _COMMON_ _COMMON_ In this example, the first time this
file is included, the symbol _COMMON_ is undefined, so the #EXIT is ignored.
Consequent times this file is included, it exits upon hitting the #EXIT directive. Note:
Due to how #INCLUDE files are counted internally, and there being a limit on
how many total files you can #INCLUDE, it’s better when working with larger projects that you do
not #INCLUDE
a file at all when already processed, rather than #INCLUDE it and #EXIT it. (See also #USES) |
|
#EXTRAOFF |
Disables
recognition of ASM11’s extended instruction set for source lines that follow
this directive. Equivalent to the –X- command line option. |
|
#EXTRAON |
Enables
recognition of ASM11’s extended instruction set for source lines that follow
this directive. Equivalent to the –X+ command line option. |
|
#EXPORT symbol[,symbol]* |
Export
one or more symbols (as if with EXP). File-local symbols cannot be
exported. If a symbol is not
currently defined, a warning will be issued. |
|
#FATAL [text] |
Similar
to the #ERROR
directive, but generates an assembler fatal error message and terminates the
assembler (possible further files in the command line supplied file list will
not be processed). |
|
#HOMEDIR [path] |
Makes
the specified path
the current home directory. Although
this cannot affect where any output files will go, it does make a difference
on where any following relative #INCLUDE files will be searched.
Relative file path
specifications will now be relative to the directory specified by the #HOMEDIR directive, including
any relative #INCLUDE references
in nested include files. If [path] is missing, the original
main file path is restored. |
|
#IF expr1 cond expr2 |
Evaluates
expr1
and expr2
(which may be any valid ASM11 expression) and compares them using the
specified cond
conditional operator. If the
condition is true, the code following the #IF operator is assembled, up to its matching #ELSE or #ENDIF directive. Cond
may be any one of: < <= =
>= > <> The condition is always evaluated using
unsigned arithmetic. If a symbol referenced in expr1 or expr2 is not defined, the
statement will always evaluate as false.
At least one space must embrace cond on each side. |
|
#IFDEF expr |
Attempts to evaluate expr, and if successful, assembles the code that follows, up to
the matching #ELSE
or #ENDIF
directive. This directive is used to
test if a specified symbol has been defined.
Symbol(s) referenced in expr must be defined before the directive for the result to
evaluate true (e.g., forward references will evaluate as false). #IFDEF without an expr
following will always evaluate to False. |
|
#IFEXISTS fpath |
It
checks for the existence of the file specified by fpath (using the same rules as those used for #INCLUDE directives) and
assembles the code that follows if the specified fpath exists. |
|
#IFINCLUDED |
Assembles
the code which follows if the file containing this directive is a file used
in an INCLUDE directive of a higher-level file (regardless of nesting
level). See also #IFMAIN |
|
#IFMAIN |
Assembles
the code that follows if the file containing this directive is the main
(primary) file being assembled. See
also #IFINCLUDED. |
|
#IFMDEF macro #IFNOMDEF macro |
#IFMDEF checks if the
specified macro exists, and if so, assembles the code that follows, up to the
matching #ELSE
or #ENDIF
directive. This directive is used to
test if the specified macro has been defined. #IFNOMDEF
does the opposite check. |
|
#IFPARM text [== text] #IFNOPARM text [= text] #IFNOPARM text [== text] Aliases: #IFB same as #IFNOPARM #IFNB same as #IFPARM |
Normally used inside macros. If text is non-blank, assembles the code that follows, up to
the matching #ELSE
or #ENDIF
directive. This directive is used to
test if a specified macro parameter has been defined. #IFPARM without text following (after macro expansion) will always
evaluate to False. text is usually a parameter placeholder (e.g., ~1~). You
can also make a case-insensitive (using the =
sign) or case-sensitive (using the == sign) comparison of
the parameter to a specific text string (with or without quotes, depending on your intent)
by separating the two text strings with an ‘equals’ (=), or double-equals
(==) sign, depending on the desired case-sensitivity. For example, #IFPARM
~1~ = * tests
if parameter one is a plain asterisk (normally used to indicate the current
location pointer.) #IFNOPARM performs the opposite test. |
|
#IFSTR text #IFNOSTR text |
Normally used inside a macro. If text is a quoted string, assembles the code that follows, up
to the matching #ELSE or #ENDIF directive. This
directive is used to test if a specified macro parameter is a string. #IFSTR without text following (after macro expansion) will always
evaluate to False. text is usually a parameter placeholder (e.g., ~1~). #IFNOSTR performs the opposite test. |
|
#IFNUM text #IFNONUM text |
Normally used inside a macro. If text represents a number, assembles the code that follows,
up to the matching #ELSE or #ENDIF directive. This
directive is used to test if a specified macro parameter is a number. #IFNUM without text following (after macro expansion) will always
evaluate to False. text is usually a parameter placeholder (e.g., ~1~). #IFNONUM performs the opposite test. |
|
#INCLUDE fpath #USES fpath |
Includes
the specified fpath
file in the assembly stream, as if the contents of the file were physically
present in the source at the point where the #INCLUDE directive is encountered.
#INCLUDE’s may be nested, up to 100 or
125 levels (the main source file counts as one level). Relative fpath specifications are always referenced to the directory in
which the main source file resides, including any relative #INCLUDE fpath references in nested
include files. #USES
is an alternative, slightly different method to include a file. It will #INCLUDE
the file specified (using the same file-finding rules as #INCLUDE) but only if the same file path has not been included (via
#INCLUDE or #USES) at least once,
already. #USES
is useful for creating #INCLUDE file dependencies
(normally, from a higher level to a lower level – e.g., an analog
temperature sensor driver module #USES
the A/D driver module, but not the other way around). This allows
directly #USING (an alias for #USES) only the module of
interest in your application, and it should take care to use whatever other
modules it requires (in a recursive sort of way). If another included module in the same application #USES the same lower-level module, it will not be included a
second time. This is similar to the
common #IFNDEF _MODULE_ _MODULE_ ...your module code goes here... #ENDIF technique
used to prevent multiple inclusions of the same file, but only have it included
the first time it is referenced.
Normally, the #IFNDEF … #ENDIF block is
found inside the file, meaning the assembler must enter the file before it
‘knows’ it doesn’t need it. The
advantage with #USES, however, is (1) that you do not need a specific symbol
definition for each file, and (2) you never enter an already included file
(which would use up a sometimes precious file count towards the maximum
number of #INCLUDE files.) Bi-directional,
or circular co-dependencies (e.g., file A depends on file B, while file B
depends on A) are possible in some cases, and then they require some extra
attention in the respective files’ internal organization, or it could not
work as you might have expected, and leave you confused by ‘spurious’ errors. In general though, you should try to avoid
them. Also,
you cannot use #USES in place of #INCLUDE for modules that
must be included multiple times (e.g., including the same SCI driver module,
once for each hardware SCI available), although you could use #USES to include a file that itself does #INCLUDE the same file multiple times. Note: The assembler will only generate a
standard error (not an assembly-terminating fatal error) if a file specified
in a #INCLUDE
(or #USES)
directive is not found. The #IFEXISTS and #IFNEXISTS directives
may be used in conjunction with #FATAL if termination of assembly is desired under such
conditions. |
|
#IFNDEF expr |
Evaluates expr and assembles the code that follows if the expression
could NOT be evaluated, usually as the result of a reference to an undefined
symbol. This directive is the
functional opposite of the #IFDEF directive. |
|
#IFNEXISTS fpath |
The
opposite of #IFEXISTS;
code following this directive is assembled if the specified fpath does NOT exist. As of version 1.61, the -Ix path will also
be searched to determine whether a file exists or not. |
|
#IFNZ expr |
Evaluates
expr
and assembles the code that follows if the expression evaluates to a non-zero
value. #IFNZ always evaluates to false if expr references undefined or forward-defined symbols. |
|
#IFZ expr |
Evaluates
expr
and assembles the code that follows if the expression is equal to zero. #IFZ always evaluates to false if expr references undefined or forward-defined symbols. |
|
#LISTOFF #NOLIST |
Turns
off generation of source and object data in the *.LST file for all lines
which follow this directive. Useful
for excluding the contents of #INCLUDE files in the *.LST file.
This directive is not shown in the *.LST file. |
|
#LISTON #LIST |
Enables
generation of source and object data in the *.LST file for the source code
following this directive. Has no
effect if list file generation is disabled (-L- command line option in effect). This directive is not shown in the *.LST file if the listing
was turned off just prior to it. |
|
#MCF [@@] #MCF2 [@@] #@MACRO
[@@] |
#MACRO tells the assembler
to treat unknown assembly language operations as possible macros. Normal instructions (including the
built-in macro instructions) have priority over macros, so macros named the
same as active built-in operations can only be called with the @ prefix. In
effect, when in this mode, the assembler automatically adds the @ symbol if an unknown operation is found
to be a macro name. In this mode, one
can invoke macros either way, with or without the @ prefix, but instructions have priority over same name
macros. Note:
To avoid problems, all macros should internally use the @macro syntax so they can
be properly expanded regardless of mode. #MCF (“Macros Come First”) is similar to #MACRO (i.e., no @ prefix is required for calling macros)
but in this case macros have priority over same-name instructions but only
when called from outside any macros.
Macro chaining (i.e., jumping to a macro from inside a macro) is still
only possible using the @ prefix when a macro name collides with an active
instruction name. So, using this
mode is 100% compatible with macros written before this mode was introduced
and does not require editing macros to use the !instruction format mentioned next. If
you’re in #MCF
mode, and you want to temporarily give priority to a real instruction
(without changing to #Macro or #@Macro mode), you must prefix it with a ! (exclamation point.) The
#MCF mode is most useful
when you want to override the functionality of any internal instruction with
something more involved (a macro), as for example, when porting code from
another CPU with similar instructions but different functionality (e.g. LDX in 68HC11 is a word operation, and it
may compile without errors in the 68HC[S]08 but with incorrect operation as
it will not affect the full HX register). I do not recommend casual use of this mode as it
may make the source code totally misleading (if instructions which are now
possibly macros aren’t what they seem but something completely different.) #MCF2 is almost the same as #MCF but it doesn’t have the restriction where macros
named the same as instructions require the @macro format from within macros. This is the most ‘dangerous’ of all available modes, since it
is always the macro which has precedence.
If you need to be certain you use a real instruction and not a
possible macro with the same name, you MUST use the !instruction format. #@MACRO turns off this option.
This is the default setting when a new assembly begins. In this mode, you can only invoke macros
with the @ prefix. This is the recommended mode for most
normal applications. Hint:
The macro is normally invoked as an instruction, which means its name must
appear after column one. Regardless of the current macro mode, when a macro
call is made using the default @macro
(or %macro) format, its invocation can start even in column one,
since it can’t ever be a symbol that starts with one of these two characters
[@ and %]. Note:
If the optional @@ parameter is provided to any of the four directives
mentioned above, macro chaining is effectively disabled, and any otherwise
‘chained’ calls now become truly nested calls (as if the @@macro format is used at all times a macro is called). WARNING: Macros written based on the
default ‘chain’ behavior may no longer operate the same (since non-@@ macro calls include an implied following mexit). To simulate the
same behavior, when the @@ option is active,
make sure you add an MEXIT command after each
otherwise ‘chained’ macro call. By the
way, this will make the macro work the same way regardless of the @@ sub-mode being in effect or not. When
the @@ sub-mode is in effect, you still need to observe the
various calling methods based on which of the three macro modes you’re
in. To cancel the @@ sub-mode, simply give any of these directives without it. |
|
Export
one or more macros in the EXP file (if one is produced). File-local macros cannot be exported. If a macro is not currently defined, a
warning will be issued. |
|
|
#MLIMIT [expr] |
Sets
the maximum macro nesting limit to the value of the optional expression. If no expression follows the default
value of 100 is used. This value
should be more than adequate for nearly all cases. Minimum value is zero (which practically
disables macro call nesting). Maximum
is 10000 (ten thousand). Note: Macro nesting uses extra memory
during assembly. You should avoid
using macro nesting if the same functionality can be achieved by using macro
chaining, or even the most efficient simple looping (MTOP instruction). |
|
#NOMLIST |
Turns
off generation of source and object data in the *.LST file for all macro body
lines which follow this directive.
Useful for excluding the body of macros in the *.LST file. |
|
#MLISTON #MLIST |
Enables
generation of source and object data in the *.LST file for all macro body
lines following this directive. Has
no effect if list file generation is disabled (-L- command line option in effect). This is the default setting. |
|
#HIDEMACROS #SHOWMACROS |
Note:
These two directives work only when the –LC- (List Conditionals = OFF) command-line option is in
effect. #HideMacros
treats all macro-specific keywords (the @macro call, mexit, mtop, endm) the same as ‘conditional’ directives only for the
purposes of display in the listing.
So, when –LC-
is in effect, they won’t appear in the *.LST file at all. This
leaves only the expanded macro contents.
When this directive is in effect, it is no longer possible to know
where a macro begins or ends, or how many times it iterates itself. Note: The corresponding macro
definitions will not display at all, regardless of the –LC mode. #ShowMacros
(re-)enables normal display. The
default setting when a new assemby begins is #SHOWMACROS. #PUSH
and #PULL will
save/restore the value of this setting. |
|
#MAPOFF |
Suppresses generation of source-line information in the
*.MAP file for the code following this directive. Symbols which are defined following this directive are still
included in the *.MAP file. |
|
#MAPON |
Enables
generation of source-line information in the *.MAP file for the code
following this directive. #MAPON is the default state
when assembly is started when map file generation is enabled (-M+ command line
option). |
|
#MEMORY addr1 [addr2] #MEMORY #OFF# |
Maps
a memory location (or range, if addr2 is also supplied) of object code and/or
data areas as valid. Use multiple
directives to specify additional ranges.
Any code or data that falls outside the given range(s) will produce a
warning (if the -O option is enabled) for each violating byte. Very useful for segmented memory devices,
etc. Addr1 and addr2 may be specified
in any order. The range defined will
always be between the smaller and the higher values. The
special keyword #OFF# removes all current definitions. See
also #VARIABLE |
|
#MESSAGE [text] |
Displays
text
on screen during the first pass of assembly when this directive is
encountered in the source. Messages
are not written to the error file.
They are meant to inform the user of options used or conditional paths
taken. |
|
#NOWARN |
Turns
warnings off. Equivalent to the –WRN- command line
option. See also #WARN |
|
#OPTRELOFF |
Disable
«BRA/BSR instead of JMP/JSR» optimization warnings. Equivalent to the –REL- command line option. |
|
#OPTRELON |
Enable
warning generation when an absolute branch or subroutine call (JMP or JSR) is
encountered that could be successfully implemented using the relative form of
the same instruction (BRA or BSR).
This option is on by default. Equivalent to the –REL+ command line option. |
|
#OPTRTSOFF |
Disable
RTS-after-JSR/BSR optimization warning (default). Equivalent to the –RTS- command line option. |
|
#OPTRTSON |
Enable
warning generation when a subroutine call (JSR or BSR) is immediately
followed by a RTS. This option is off
by default. Command-line option -RTS+ does the same thing. |
|
#PARMS [char|SPACE] |
Allows changing the delimiter used to
separate macro parameters when invoking the macro. If char
is defined the new delimiter will be the same as char. If there is no
character following the directive, the default parameter delimiter (a
comma) will be used. To use a regular space as a parameter separator, the [char] part of the command
should be the special keyword SPACE (case-insensitive). #PUSH and #PULL will save/restore
the value of this setting. |
|
#PPC |
#PPC
(stands for Preserve PC) simply keeps a copy of the current :PC value to be used later by the :PPC internal symbol. #PUSH and #PULL will save/restore
the value of this setting. |
|
#PROC |
Advances
the @@ local label
counter. See also PROC |
|
#RENAME oldname,newname #REMACRO oldname,newname |
Renames
a macro from its current (old) name to a new name. An error message is issued if the old
name is not a defined macro, the new name is a defined macro, or either name
is an invalid symbol name. #REMACRO is the same as #RENAME except that it does
NOT check if the new name exists. If
it exists, there will now be one extra instance of that macro. Note: The most recently defined macro
of the same name is visible when more than one macro share the same name. #DROP-ping
the macro always drops the visible instance, making a possible previous
instance now visible. Tip: An example of where #RENAME might be useful: Say, you have a library (or OS system)
macro that is called many times in your application, but you want to modify
that macro’s behavior just for this one application. Your options are: [1] Write a new (differently named)
macro, and change all calls from the old macro to new macro. Problem: If some of these calls are inside
shared library code, you can’t change those calls, as it will affect other
applications using those macros, as well.
Too much work, and error prone. [2] Alter the library macro to include
the new behavior. Problem: Other
applications may not like the new behavior. [3] Use #RENAME
in your application to have the old library macro change name just for this
application’s sake. Then, use the
original name to write a brand new compatible macro but with the new
behavior. It is also now possible for
the new macro to ‘borrow’ the functionality of the old macro (by calling it
internally as needed), so the new macro doesn’t necessarily have to repeat
the whole original macro body. This
allows for an easy way to extend or replace any general-purpose library
macros for each application, separately. Example for #REMACRO
that allows front-ending a previous macro to add code before and after the
macro call. a macro #Message Inside
original ~0~ endm a remacro #Message Inside
inner ~0~ #rename ~0~,_{:totalmacrocalls}_ @@a #remacro
~0~,~self~ #Message Inside
inner ~0~ endm a remacro #Message Inside
outer ~0~ #rename
~0~,_{:totalmacrocalls}_ @@a #remacro ~0~,~self~ #Message Inside
outer ~0~ endm @a #Message
----------------------------- @a |
|
#S19FLUSH |
Forces
the immediate termination of an S-record line when encountered, rather than
waiting for the record to reach the size specified by the –Rn command line directive.
This directive may be used to make identification of the end of code
blocks easier when viewing the *.S19 file. |
|
#PAGE |
Outputs a Form Feed (ASCII 12) character followed by a Carriage
Return (ASCII 13) in the *.LST file just before displaying the line that
contains this directive. |
|
#PUSH |
Pushes
on an internal stack the current segment and the current settings of
the following directives: MAPx, LISTx, CASEx, EXTRAx, SPACESx, OPTRELx, OPTRTSx, [NO]WARN, TRACEx, MACRO, @MACRO, MCF,
MACROSHOW, MACROHIDE, :PSP, :PPC, TRACE[ON/OFF], MLISTx, and TABSIZE. Useful in
included files that want to change any of these options without affecting
parent/sibling files. See also #PULL |
|
#PULL |
Pulls
from an internal stack the most recently pushed options. See also #PUSH |
|
#RAM |
Activation
of the RAM segment. Default starting value is $0000. |
|
#ROM |
Activation
of the ROM segment. Default starting value is $D000. This is the default segment if none is
specified. |
|
#SEGn |
Activation
of the SEGn segment (n is a number from 0 through 9). Default starting value for all ten
segments is $0000. |
|
#TABSIZE n |
Specifies the field width of tab stops used in the source
file. Proper use of this directive
ensures that the *.LST files generated by ASM11 are formatted in the same way
as your source files appear in your text editor. This directive overrides the setting of the –Tn command line option at the point in the source file(s) in
which it is encountered. |
|
#TEMP [expr] |
#TEMP
simply assigns any value (possibly the result of an non-forward expression)
to the internal general-purpose :TEMP variable. If no
expression follows #TEMP, :TEMP is zeroed. :TEMP can be used any time in lieu of defining any ‘helper’
symbol for intermediate calculations (either inside or outside macros). The only restriction is that :TEMP always refers to the most recent #TEMP
directive, so it cannot be used to look forward. Although :TEMP is a single
variable, its use is transparent in relation to macros. In other words, changing :TEMP from within any macro does not affect the value of :TEMP outside all macros, or macros above the current level. Although macros inherit their initial value of :TEMP from their higher level (either a caller macro, or normal
code), they do not affect their parent’s :TEMP
value, so you can use it without worrying about side effects from any
intermediate macro calls. :TEMP is also assigned indirectly when used as label with
th any of the following directives/pseudo-ops: NEXT,
NEXP, SETN, and #AIS |
|
#TRACEON #TRACEOFF |
#TRACEON enables generation of source-line information in the *.MAP
file for any code found in the body of macros following this directive. The map info is generated in such a way
that while tracing the debugger will display the actual source of the
macro. This can be used globally (to
affect all macro invocations), inside a specific macro (to debug that one
macro), or around a specific macro invocation (to debug that one macro call.) #TRACEOFF
turns this option off making macros appear as a single line in the
debugger. #TRACEOFF is the default state when assembly is started. |
|
#VARIABLE addr1 [addr2] #VARIABLE #OFF# |
Maps
a location (or range, if addr2 is also supplied) of variable allocation area
(normally in RAM) as valid. Use
multiple directives to specify additional ranges. Any RMB
or DS definitions that
fall (fully or partially) outside the given range(s) will produce a
warning (if the -O option is enabled) for each such definition. Addr1 and addr2 may be specified in any
order. The range defined will always
be between the smaller and the higher values. The
special keyword #OFF# removes all current definitions. See
also #MEMORY |
|
#VECTORS |
Activation
of the VECTORS segment. Default starting value is $FFD6. |