ASM8
A
two-pass absolute macro cross-assembler for the 68HC08/HCS08/9S08
ASM8 - Copyright © 2001-2011 by Tony Papadimitriou <tonyp@acm.org>
ASM8
[-option [...]] [[@]filespec [...]] [>errfile]
·
option(s)
may appear before, in between or after filespec(s).
·
option(s)
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. Currently, error redirection is only possible with the DOS
version.
·
All shaded
areas are pertinent to the MMU enabled versions (Win32/Linux only).
·
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
(MMU not withstanding), 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 bps rates or 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)
Option |
Default |
Description |
|
|
|
|
|
-C[±] |
-C- |
Label case sensitivity: + = case
sensitive (See also #CASEON/#CASEOFF) |
|
-Dlabel [:expr] |
|
Use up to ten times to define symbols
for use with conditional assembly (IFDEF and IFNDEF directives).
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 be used as an #INCLUDE file for other
programs. This allows for automatic
creation of include files with global exported 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. |
|
-HCS[±] |
-HCS- |
When on, the assembler understands the
extended HCS08 instruction set. The
cycle counts in the listing also reflect the HCS08 core. To check the current status of this switch
look at the help screen’s second line from top. The software will say it’s either a MC68HC08 or a MC68HCS08
assembler based on this setting. See
also the directives #HCSON, #HCSOFF, #IFHCS, and #IFNHCS |
|
-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. |
|
-J[±] |
-J+ |
Effective only while
the MMU is disabled: When on, CALL/RTC
instructions are treated as if they were JSR/RTS
instructions, respectively. When off, CALL/RTC instructions produce errors. Makes it possible to write common library functions using CALL/RTC instead of JSR/RTS
and have them used in all MCUs, regardless if they have an MMU or not. See
also the directives #JUMP, and #CALL |
|
-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. |
|
-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 compatible format (possibly not useful for HC08), 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. |
|
-MMU[±] |
-MMU- |
Enable the MMU features (e.g., CALL/RTC
instructions, 24-bit addresses and expressions). See also the directives #MMU, #NOMMU, #IFMMU, and #IFNOMMU |
|
-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 do not affect this. |
|
-Q[±] |
-Q- |
Specifies quiet run (no output) when
redirecting to an error file (DOS only).
Useful for IDEs that call ASM8 and don’t want to have their display
messed up. Beginning with v1.29, 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 while maximum is 250. |
|
-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). |
|
-S2[±] |
-S2- |
Force the generation of S2 records
(24-bit addresses) even for 16-bit addresses. Although 24-bit addresses are enabled, no MMU features are
enabled. Useful mostly for forcing
16-bit addresses to appear as 24-bit (with leading byte as $00) so that S19
loaders can use that as the PPAGE value.
See also #S1
and #S2 |
|
-S9+ |
This option can be used to turn off
generation of the final S9 (or S8) 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. |
|
|
-SH[±] |
-SH- |
Include dummy «S0» record (header) in
object file (only if –S+). |
|
-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 IDEs). |
|
-Tn |
-T8 |
Specifies
tab field width to use in *.LST files.
Tab characters embedded in the source file are converted to spaces 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-68HC08-standard mnemonics and simulated index modes in source files. (See also EXTRAON/EXTRAOFF) |
|
-Z[±] |
-Z- |
Convert the paged addresses (PAGE:ADDR16) to linear (extended)
address in the produced S19 file(s).
In effect, all addresses within the ranges $xx8000-$xxBFFF are converted to their linear format. The code or listing is not affected at
all. This is useful for S19 loaders that expect addresses in
linear format, instead of paged format. Warning: The ambiguous case
of $8000-$BFFF
is treated as PAGE0,
which is converted to linear addresses: $000000-$003FFF. If you want to
place something at PAGE2, position it (ORG)
at $028000, which will
convert to linear address $008000. |
|
-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 on command line
to the ASM8 executable (DOS), or ASM8.CFG file (Win/Linux). The user-specified options become the
default values used by ASM8 in subsequent invocations. Filespec(s)
on the command line are ignored.
Assembly of source files does not take place if this option is
specified. |
All
shaded areas are pertinent to the MMU
enabled versions (Win32/Linux only).
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; ASM8 always processes the source file to the end of file. If expr is specified, the word result of the final END directive is encoded in the S9 record
of the object file. If the expr specified is 24-bit (bits 23-16, collectively, are
non-zero), which is possible only when the MMU option is enabled, the
24-bit result is encoded in the S8 record of the object file (no S9 record is
produced in that case). |
|
ENDM |
Ends
definition of a macro. |
|
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. |
|
FAR expr[,...] |
Define
24-bit word(s) when the MMU is enabled.
expr
may be a constant numeric, a label or an expression. expr is always interpreted as a 24-bit quantity, and is stored
in the object file at the current location counter in big-endian order. If, however, the MMU option is disabled,
FAR is treated as DW. |
|
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 automatically
appends 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. |
|
... REMACRO ... |
MACRO
begins the definition of a new macro. REMACRO
begins the definition of a new macro over a possibly existing same name
macro. Hint: Use #DROP to remove the latest definition, restoring the previous
one, if any. REMACRO is same as MACRO
when used with special ? macro.
§
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).
SPECIAL CASE: When inside a string, the expression will be evaluated
when the string is processed by the assembler, which is after macro expansion
of the various placeholders. This
means we have lost our chance to expand this placeholder. But, we can use the \@ instead of quotes for strings inside a
macro which contain ~n.s.l~ embedded expressions, and not only those (example: fcc \@~{PARM}.{FROM}.{LENGTH}~\@
to have it expand correctly. Because
of the \@ the string
does not appear as a string yet, and the expressions can be calculated during
macro expansion. This way all
expressions become simple constants, and the placeholder can be processed. Finally, the \@ dummy string delimiters are turned into single, double, or
back quotes, depending on which of these three doesn’t appear in the string
at all, making the whole thing a proper string. IMPORTANT
COMPATIBILITY ISSUE: A couple or
so versions compiled prior to 2010/09/24 23:00 used @@ instead of \@. The @@ was an unfortunate selection of dummy quote delimiter and
it had to be replaced with a better one (\@) even though it
meant possibly causing problems with existing code (hopefully, not that many
macros utilizing this feature were written in the few days the feature has
been available with the wrong delimiter) because it caused syntax errors in
certain cases, e.g. if single character string contained the @ char (with or
without macro parameter expansion), or labels containing @@ inside their name.
|
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 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. |
|
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. ASM8 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 spaces display, use the Alt-255 character, as many
times as needed.
·
All shaded
areas are pertinent to the MMU enabled versions (Win32/Linux only).
Directive |
Description |
|
|
|
|
#AIS symbol |
#AIS
checks the current value of the :SP internal variable against the most recent AIS instruction’s value, and issues a
warning if the two numbers do NOT differ by the exact value in the symbol (note:
a plain symbol, not an expression), indicating a possible stack
frame definition error (assuming correct placement of the relevant directives). The warning also shows
the correct AIS instruction that is required to correct the problem.
This directive makes
it very easy to correct the numeric value in AIS
instructions to match the following stack frame definition (normally
made using the internal :: symbol in the various #SPAUTO modes, and
the next/setn method for defining records/structures. ) This is useful to prevent having to define
the stack frame before the AIS instruction using a one-based starting
offset just so you can use a label with AIS and then
having to re-define it for dynamic assignment of offsets based on the current
:SP.
The associated :AIS symbol returns the difference between the current :SP and the value saved
during the most recent AIS instruction. This
can be used to de-allocate just the number of stack bytes that are still left
on the stack between the two points in your source (inclusive of the previous
AIS
instruction). This is only meant for
use in #SPAUTO
modes, which automatically adjusts the current value of the :SP internal symbol. #PUSH
and #PULL will
save/restore the value of this setting. Example use:
#spauto Subroutine ais
#-4 ;local data ? set
:: ?Parm1 setn ?,2 ?Parm2 setn
?,2 #ais
? ;check
frame definition |
|
#CALL |
Effective only while
the MMU is disabled: When active, CALL/RTC
instructions are NOT treated as if they were JSR/RTS
instructions, but they issue errors instead.
See also the directives #JUMP, #MMU, #NOMMU Equivalent to the –J- command line option. |
|
#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. 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. 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. |
|
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 $FE00. |
|
#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 $0000. |
|
#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 an 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 ASM8’s extended instruction set for source lines that follow
this directive. Equivalent to the –X- command line option. |
|
#EXTRAON |
Enables
recognition of ASM8’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 list will not be processed). |
|
#HCSOFF |
Disables
the HCS08 instruction set mode. See
also #IFHCS #IFNHCS #HCSON Equivalent to the –HCS- command line option. |
|
#HCSON |
Enables
the HCS08 instruction set mode. See
also #IFHCS #IFNHCS #HCSOFF Equivalent to the –HCS+ command line option. |
|
#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 ASM8 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. |
|
#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 |
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. |
|
#IFHCS |
Assembles
the following code if the assembler is in the extended HCS08 instruction set
mode. See also #IFNHCS #HCSON #HCSOFF |
|
#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. |
|
#IFMMU |
Assembles the code that follows if the
MMU option is enabled. See also the
directives #MMU,
#NOMMU,
and #IFNOMMU |
|
#IFNOMMU |
Assembles the code that follows if the
MMU option is disabled. See also the
directives #MMU,
#NOMMU,
and #IFMMU |
|
#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. |
|
#IFSPAUTO |
Assembles
the code that follows, up to the matching #ELSE or #ENDIF directive, if the assembler is currently in #SPAUTO (automatic SP
adjustment) mode. See also #SPAUTO #SP |
|
#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. |
|
#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. The -Ix directory will be used also to
determine if a file exists or not. |
|
#IFNHCS |
Assembles
the following code if the assembler is in the regular HC08 instruction set
mode. See also #IFHCS #HCSON #HCSOFF |
|
#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. |
|
#IFTOS expr |
If
top-of-stack evaluates expr+:SP (+:SP is implied) and
assembles the code that follows if the expression is equal to one (when in #SP[AUTO] modes), or zero
(when in #SP1
mode), i.e., expression points to top-of-stack in all modes. #IFTOS always evaluates to false if expr references undefined or forward-defined symbols. Useful mostly in #SP[AUTO] modes. |
|
#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. |
|
#JUMP |
Effective only while
the MMU is disabled: When active, CALL/RTC
instructions are treated as if they were JSR/RTS
instructions, respectively. Makes
it possible to write common library functions using CALL/RTC instead of JSR/RTS
to be used in any MCU, regardless if an MMU is available/used or not. See also the directives
#CALL, #MMU, #NOMMU Equivalent to the –J+ command line option. |
|
#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. |
|
#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). |
|
#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 begi |