ASM11

A two-pass absolute macro cross-assembler for the 68HC11

 

 

Quick Reference Guide

ASM11 - Copyright © 1998-2010 by Tony Papadimitriou <tonyp@acm.org>

Last Update: September 4, 2010 for ASM11 v6.10


Command-Line Syntax and Options

 

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 to keep 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)

5                    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.

-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+).

-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.  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.

 

 


Source File Pseudo-Opcodes (Pseudo-Instructions)

 

Pseudo-Op

Description

 

 

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 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

Begins definition of a macro.

  • Macros must be defined anytime before they are invoked, and they can be invoked until the end of the current assembly (for global macros), end of current file (for local macros), or until a #DROP directive undefines them, in either global or local case.
  • Macros are invoked using the @MacroName[,parm separator] syntax, by default (see #MACRO, #@MACRO and #MCF directives).  Note: You can also use the %macro call syntax to force the macro counters (:MINDEX, :INDEX, :LOOP) to reset, as if you had dropped and recreated the macro.
  • The macro name may be followed by a comma and any non-alphabetic single character (if more characters found, only the first matters).  If this parameter override option is found, then the character right after the comma will act as a one-time parameter delimiter (just for this macro call.  The #PARMS defined delimiter will not be affected.)  If the character is a space, it does not require yet another space as field separator.
  • The macro may refer to yet undefined labels or macros, as the code or definitions inside it are not parsed until the macro is actually used, if at all.
  • Local macro names start with the ? symbol (like normal local labels).
  • The special local macro named ? (just a single question-mark) is to be used ad-hoc.  This one special macro name is automatically dropped (without warning) at each new redefinition.  It’s useful for quickly defining a temporary macro to be used immediately afterwards, and considered discarded later.

§         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 parm separator.)

§         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 for 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 maintaing 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.

  • Macro-only labels must include the string $$$ anywhere inside their name (except at the very beginning), e.g. Loop$$$
  • Parameter text replaces placeholders anywhere within the body of the macro (label, operation, operand, comment fields) without regard to context.  Parameter placeholders are ~0~ thru ~9~ (where ~0~ is reserved for the macro name itself, and ~1~ thru ~9~ for actual parameters.)
  • The body of a macro may contain embedded expressions (in any field, even comments) of the form {<expr>}, like one can do with strings, where <expr> is any valid expression, normally including some parameter placeholder(s).  Expressions are evaluated last, after expansion of parameter placeholders.
  • To accommodate indexed mode within any one parameter (provided the macro is called with a non-comma parameter separator), you can use the following variations of the placeholders: ~n,~ and ~,n~ (where n is the number 1 thru 9) and the comma position (either after or before the number) defines whether we want the part before the index (excluding the comma), or the index itself (including the comma), respectively.  For example, the instruction lda ~1,~+1~,1~ will expand correctly whether parm ~1~ contains an index or not.  (Using the simpler lda ~1~+1 will not expand with the intended behavior, as the +1 will follow the index, and not the offset before the index.)  If no index is within the parameter, ~n,~ is the same as ~n~ while ~,n~ is null.  The assembler will pick anything following a possible comma within a parameter as being an index (so you could get creative and use the feature for other purposes also).
  • The special placeholder ~#~ returns either a null string or the character # if the first parameter’s (~1~) first character is a # (possibly, indicating immediate mode use).  With conditional assembly (e.g., #IFPARM ~#~) one can treat the ~1~ parameter differently, assuming immediate mode.
  • Similarly, the placeholder ~#n~ (where n is a number from 1 thru 9, zero also accepted but it is pointless) returns the parameter part after a possible # sign, if one is present.  This allows to get an immediate mode type parameter in a form (stripped of the # symbol) that can be used in expressions (for example, in an #IF directive expression).
  • Since one may often call a macro with a non-comma delimiter (such as when a parameter contains a comma in an indexed operand – e.g. 1,sp), a possible chained macro call passing this parameter to another macro, or to self while looping, must use the same parameter delimiter that was used to call the original macro, or else the parameter may not be passed on correctly, or not even as a single parameter.  Using the default (a comma) is problematic in those cases.  To solve this problem, two equivalent special placeholders have been introduced.  One is the ASCII code 149 [•] (e.g., use the ALT-7 method for entry in Win-PCs), and the other is the two-character sequence \, (a backslash followed by a comma) which should work in all environments.  Either of these placeholders will be replaced by the same delimiter as the one used for the most recent macro call (either by default or by override), unless there is a new explicit one-time delimiter override (@macro,char format).
  • The special placeholder ~label~ (case-insensitive) returns the actual text of a label appearing in the label column of the last macro invocation (after expanding possible label embedded {<expr>}).  This can be used with ‘function-like’ macros that need to set a label to a specific value (without having to pass the name of the label as a regular parameter).  If no label is used in the same line as the macro invocation, then it returns a null (empty) string.  If, however, no label is used with a chained macro invocation (a macro invocation occuring from inside a macro) then the text is not changed from the original macro’s.  This way, a macro can chain to itself (for looping) and still have the ~label~ placeholder expand correctly.
  • The placeholder ~@~ is an alias for the full list of placeholders separated by • (starting from ~1~).   Useful if you want to pass all parameters to another macro.  The sequence produced by ~@~ is: ~1~•~2~•~3~•~4~•~5~•~6~•~7~•~8~•~9~
  • The placeholder ~@@~ is an alias for the full list of placeholders separated by • but starting from ~2~.  Useful if you want to pass the remaining parameters to the same macro when looping (assuming each loop only processing the first parameter, until that becomes null).  The sequence produced by ~@@~ is: ~2~•~3~•~4~•~5~•~6~•~7~•~8~•~9~
  • Trailing commas due to macro expansion of null parameters are automatically removed.
  • Order of placeholder expansion is: ~label~, ~#~, ~#n~, ~n~ (where n = 0..9, in that order), \,, and .
  • During macro invocation, any parameter text may contain embedded {<expr>}, like one can do with strings, where <expr> is any expression, possibly including some parameter placeholder(s).
  • Macros cannot #INCLUDE files.
  • Macros cannot define other macros.
  • Macros cannot temporarily invoke other macros.  (No nesting.)
  • Macros, however, can chain to self or other macros (with no return).  This allows, among other things, for creating loops, making macros very powerful.
  • To break out of an endless macro loop, press [ESC].
  • Macro labels may be case-sensitive (depending on #CaseOn/Off directives) when defined, but are always case-insensitive when invoked (like normal opcode names).
  • Virtually unlimited number of macro definitions (memory permitting.)
  • Virtually unlimited size of each macro (memory permitting.)
  • Unlimited number of macro invocations (all internal macro counters are 32-bit).

MEXIT

Causes early exit from a macro expansion.  (Normally, used with conditionals.)

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.

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]

Sets the internal :CYCLES to zero (if expression is missing) or any arbitrary value.  This 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).

 

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.

#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: »

#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.

#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).

#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 [= text2]

#IFNOPARM text [= text2]

Normally used inside a macro.  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 comparison of the parameter to a specific text2 string (with or without quotes, depending on your intent) by separating the two text strings with an ‘equals’ (=) sign.  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.

#INCLUDE 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.  Up to 100 INCLUDEs may be used and they may be nested, up to 100 levels deep (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.

 

Note: As of version 1.46, ASM11 will only generate a standard error (not an assembly-terminating fatal error) if a file specified in a #INCLUDE 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.

#MACRO

#MCF

#@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 68HC[S]08 is a byte operation, and it may compile without errors in the 68HC11 but with incorrect operation as it will affect the full X 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.)

#@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.

#MLISTOFF

#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.

#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]

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.  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).

#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 options: MAPx, LISTx, CASEx, EXTRAx, SPACESx, OPTRELx, OPTRTSx, WARN, NOWARN, TRACEx, MACRO, @MACRO, MCF, 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 last pushed segment and settings of the following options: MAPx, LISTx, CASEx, EXTRAx, SPACESx, OPTRELx, OPTRTSx, WARN, NOWARN, TRACEx, MACRO, @MACRO, MCF, MLISTx, and TABSIZE.  Useful in included files that want to change any of these options without affecting parent/sibling files.  You can use PULL even if haven’t used PUSH; no action will take place.  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.

#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]

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.  See also #MEMORY

#VECTORS

Activation of the VECTORS segment. Default starting value is $FFD6.

#WARN

Turns warnings on.  Equivalent to the -WRN+ command line option.  See also #NOWARN

#WARNING [text]

Similar to the #ERROR directive, but generates an assembler warning message instead of an error message.

#XRAM

Activation of the XRAM segment.  Default starting value is $2000.

#XROM

Activation of the XROM segment.  Default starting value is $8000.

#UNDEF symbol[,symbol]*

Undefines one or more symbols.  If a symbol is not currently defined, a warning will be issued (to protect from possible typing errors).

Careless, or simply wrong use of this directive can lead to multiple side errors or warnings (please note this is a two-pass assembler).

If you simply want to redefine the value of a symbol, prefer using the SET pseudo-op, rather than #UNDEF followed by another symbol definition.

#UNDEF can be used, for example, to completely remove unrelated or conflicting conditionals.


Note: [text] in directives and all strings may contain expressions enclosed in curly brackets, e.g. {expr}.  The expression may not contain spaces (regardless of the –SP option state, or #SPACESON directive.  An optional format modifier (case-insensitive) within parentheses after the expression can force the display in the specified format.  (D) for default/decimal, (H) for hex, (S) for signed decimal, (1) thru (4) (or, thru (9) for the 32-bit versions) for the corresponding number of decimal places after division by 10n where n is a number from 1 to 4 (or 9), and (X) for eXpanded.  If no format modifier is used, (D) is assumed.  Some examples using this feature:

 

ROM EQU $F000

#Message ROM is at {ROM}

will display:

ROM is at 61440

 

Adding a format modifier will have the following effect:

 

#Message ROM is at {ROM(x)}

will display:

ROM is at 61440 [$F000]

 

#Message ROM is at {ROM(d)}

will display:

ROM is at 61440

 

#Message ROM is at {ROM(h)}

will display:

ROM is at $F000

 

#Message ROM is at {ROM(s)}

will display:

ROM is at -4096

 

It can also be used in strings, like so:

 

VERSION equ 101 ;Firmware version as x.xx

MsgVersion fcs ‘Firmware v{VERSION(2)}’,LF

is equivalent to

MsgVersion fcs ‘Firmware v1.01’,LF

 

but it will automatically adjust the MsgVersion string each time the symbol VERSION changes value.  No need to re-adjust all relevant messages manually.

 

An expression that cannot be evaluated (due to forward references or undefined symbols) will display as three question marks (???) in directives, but no error or warning message will be issued.  When used in strings, however, errors will be displayed as usual.

 

To prevent an expression evaluation in directives, enclose the [text] that contains the curly brackets within quotes.

 

To prevent an expression evaluation in strings, break the string into two so that both curly brackets are not part of the same string, e.g.:

 

instead of fcc ‘{Hello}’ which tries to evaluate the symbol Hello use: fcc ‘{‘,’Hello}’.

 


Internally defined symbols

 

Some special internal symbols are defined by the assembler.  All such symbols begin with a colon (:) character.  Currently, the following internal symbols are defined:

 

§         :YEAR returns the year at assembly time (e.g., 2010) Hint: Use :YEAR\100 for two-digit year.

§         :MONTH returns the month at assembly time (e.g., 9)

§         :DATE returns the date at assembly time (e.g., 4)

§         :CRC returns the current value of the running user CRC

§         :S19CRC returns the current value of the running S19 CRC.

§         :CYCLES returns the current value of the cycles counter, and then it is reset to zero.

§         :TOTALMACROCALLS returns the current value of the total macro invocations.  Use it for display, or even to restrict macro use (e.g., #IFNZ :TOTALMACROCALLS … #ERROR No macros allowed for this application … #ENDIF).

§         :MACRONEST returns the current value of the macro (chain) ‘loop level’ regardless if calling the same, or a different macro (think of it as the ‘nesting level’).  A value of zero is returned if used outside any macros.  First level is number 1.  Each time the top-level macro is called, the number is reset to 1.  Each time the same or a different macro is called from within the current macro, the number is incremented by 1.  The macro (chain) can also initialize itself during, say, count one.

§         :MACROLOOP (or, simply, :LOOP) is similar to :MACRONEST but it returns the current value of the macro ‘loop level’ only for the current macro.  A value of zero is returned if used outside any macros.  First level is number 1.  Each time the macro is called from outside any macros, or from a different macro, the number is reset to 1.  Each time the macro calls itself, the number is incremented by 1.  This can be used as an automatic loop counter.  The macro can also initialize itself during, say, count one.  This differs from :MACRONEST in that chained macro calls will restart this counter for each new macro.  This counter is also reset with a %macro syntax call.

§         :MACROINDEX (or :MINDEX) returns the current value of the current macro’s number of invocations.  A value of zero is returned if used outside any macros.  First call of each macro is number 1.  If the specific macro is dropped and re-created, the number is reset (it is, afterall, a new macro).  An example use is to create different labels at each invocation (not to be confused with automatic $$$ label generation, which assumes values based on :TOTALMACROCALLS and cannot be guaranteed to take sequential values between consecutive calls of the exact same macro since other macros may have increased the counter in between), or instruction offsets (e.g., with the special ad-hoc macro named “?”), etc.  This counter is also reset with a %macro syntax call.

§         :INDEX returns the next value of the current macro’s internal user index.  A value of zero is returned if used outside any macros.  First use in each macro is number 1.  If the specific macro is dropped and re-created, the number is reset (it is, afterall, a new macro).  Its use is similar to :MACROINDEX but there is a significant difference.  :INDEX is only updated each time it is accessed, regardless of how many times the macro is actually called.  So, if used inside a conditional block of code, it will only be incremented when that part is expanded.  Note: Because of the auto-increment on access, if you want to use the same value more than once in the same macro invocation, you must first assign the value to some label, and then use the label, instead.  This counter is also reset with a %macro syntax call.

 

Notes about :cycles:

§         The cycles counter is reset to zero right after it is accessed.  To count cycles for a section of code, you must access :cycles twice, once before the code section to reset its value to zero (if not already zero from a previous access to :cycles or a #CYCLES directive), and once right after the code section to get the accumulated cycles.

§         Because of the auto-reset on access, if you need to use the same value in more than one place at a time (e.g., code and #MESSAGE directive), you must assign it to a label first, then use the label.

§         The obvious advantage is that if you alter code as in the example loop below (e.g., by adding conditional early escape code inside the loop), it will still be timed correctly without requiring a manual adjustment of the delay constant.  Another advantage is that conditionally enabled code will be accounted for correctly in all cases, again without requiring a manual recalculation for each conditional case.

§         Example use of :cycles that automatically calculates the appropriate delay constant:

 

                    #Cycles                       ; reset cycles counter

Delay10ms           pshx

                    ldx       #10*BUS_KHZ-?ExtraCycles/?LoopCycles

?ExtraCycles        equ       :cycles             ; grab counter (and reset)

?Delay.Loop         dex

                    bne       ?Delay.Loop

?LoopCycles         equ       :cycles             ; grab counter (and reset)

                    pulx

                    rts

?ExtraCycles        set       ?ExtraCycles+:cycles

 

(SET instead of EQU allows re-using symbols, so you can use it to accumulate related cycles.)
Example assembly code for calculating user CRC

 

;*******************************************************************************

; Purpose: Calculate the same user CRC as that produced by ASM11

; Input  : X -> First byte of block

;        : Y -> Last byte of block

;        : D = Initial/Previous CRC

; Output : D = updated CRC

; Note(s): Call repeatedly for different address ranges, if skipping sections

; Call   :          ldd       #CRC

;        :          ldx       #StartAddress

;        :          ldy       #EndAddress

;        :          jsr       GetAsmCRC

 

?                   set       0

?StartAddress       next      ?,2

?EndAddress         next      ?,2

?CRC                next      ?,2

 

GetAsmCRC           pshx

                    pshy

 

                    pshd                          ;CRC

                    pshy                          ;ending address

                    pshx                          ;starting address

                    tsy                           ;Y -> stack frame

 

?GetAsmCRC.Loop     cmpx      ?EndAddress,y

                    bhi       ?GetAsmCRC.Exit

 

                    sta       COPRST              ;in case of many iterations

 

                    lda       ,x

                    beq       ?GetAsmCRC.Next

                    cmpa      #$FF

                    beq       ?GetAsmCRC.Next

 

                    ldb       ?StartAddress+1,y

                    mul                           ;low address with data byte

                    addd      ?CRC,y

                    std       ?CRC,y

 

                    lda       ,x

                    ldb       ?StartAddress,y

                    mul                           ;high address with data byte

                    addb      ?CRC,y

                    stb       ?CRC,y

 

?GetAsmCRC.Next     inx

                    stx       ?StartAddress,y

                    bra       ?GetAsmCRC.Loop

 

?GetAsmCRC.Exit     pulx

                    puly

                    puld

 

                    puly

                    pulx

                    rts

 

Example coding for skipping CRC calculation for volatile sections

 

?crc                set       :crc                ;use SET, not EQU

 

       ;CODE/DATA TO SKIP FROM CRC CALCULATION HERE

 

                    #CRC      ?crc


Expression Operators and Other Special Characters

Recognized by Asm11

 

·        Expressions are evaluated in the order they are written (left to right).
All operators have equal precedence.

·        Avoid inserting spaces between values and operators (unless using -SP+ switch and semicolon beginning comments).

 

Operator

Description

 

 

+

Addition

-

Subtraction

When used as a unary operator, the 2’s complement of the value to the right is returned.

*

Multiplication

Can also be used to represent the current location counter.

/

Integer Division (ignores remainder)

\

Modulus (remainder of integer division)

=

‘Equal to’ comparison for the $IF directive.

<>

‘Not equal to’ comparison for the $IF directive.

>=

‘Greater than or equal to’ comparison for the $IF directive.

>

Shift right – operand to the left is shifted right by the count to the right.

Also used to specify extended addressing mode.

‘Greater than’ comparison for the $IF directive.

<=

‘Less than or equal to’ comparison for the $IF directive.

<

Shift left – operand to the left is shifted left by the count to the right.

Also used to specify direct addressing mode.

‘Less than’ comparison for the $IF directive.

&

Bitwise AND

|

Bitwise OR

^

Bitwise XOR (exclusive OR)

~

Swap high and low bytes (unary):  ~$1234 = $3412

Useful for converting word values from big-endian to little-endian or the inverse.

[[

Extract low 16 bits (unary):  [[$123456 = $3456

]]

Extract high 16 bits (unary):  ]]$123456 = $0012

[

Extract low 8 bits (unary):  [$1234 = $34

]

Extract high 8 bits (unary):  ]$1234 = $12

$

Interpret numeric constant that follows as a hexadecimal number.

Can also be used to represent the current location counter.

%

Interpret numeric constant that follows as a binary number

¢  `  ²

Any one of these characters (single, back, or double-quote) may be used to enclose a string or character entity.  The character used at the start of the string must be used to end it.

#

Specifies immediate addressing mode

@

Specifies direct addressing mode (same as «<»)


ASM11 Extended Instruction Set

 

The instructions listed below are not actually new instructions, rather, internal macros that generate one or more 68HC11 CPU instructions.  These instructions are only recognized if the extended instruction set option is enabled (-X+ command line option or #EXTRAON processing directive).

 

Mnemonic/Syntax

Description

 

 

AIX #word

Add Immediate X the 16-bit value #word (signed or unsigned). Equivalent to XGDX / ADDD #word / XGDX

AIY #word

Add Immediate Y the 16-bit value #word (signed or unsigned). Equivalent to XGDY / ADDD #word / XGDY

LDA operand

Same as:                                        LDAA operand

LDB operand

Same as:                                        LDAB operand

STA operand

Same as:                                        STAA operand

STB operand

Same as:                                        STAB operand

ORA operand

Same as:                                        ORAA operand

ORB operand

Same as:                                        ORAB operand

PSHD

Push D:                                           PSHB / PSHA

PULD

Pull D:                                              PULA / PULB

CMPD operand

Same as:                                        CPD operand

CMPX operand

Same as:                                        CPX operand

CMPY operand

Same as:                                        CPY operand

CLRD

Clear D:                                         CLRA / CLRB

CLRX

Clear X:                                          LDX #0

CLRY

Clear Y:                                          LDY #0

COMD

1’s Complement D:                    COMA / COMB

NEGD

2’s Complement D:                    COMA / COMB / ADDD #1

XGAB

Exchange A and B:                    PSHA / TBA / PULB

ROLD

Rotate Left D:                              ROLB / ROLA

RORD

Rotate Right D:                           RORA / RORB

INCD

Increment D:                               ADDD #1

INCX

Increment X:                                INX

INCY

Increment Y:                                INY

DECD

Decrement D:                              SUBD #1

DECX

Decrement X:                              DEX

DECY

Decrement Y:                              DEY

LBRA addr16

Long relative branch:               (22 bytes/69 cycles)

Warning! Generates considerable code, use with care

LBSR addr16

Long relative subroutine call: (32 bytes/92 cycles)

Warning! Generates considerable code, use with care

GETX #word

Get #word bytes of stack storage pointed to by X for temporary use.

Equivalent to TSX / XGDX / SUBD #word / XGDX / TXS

GETY #word

Get #word bytes of stack storage pointed to by Y for temporary use.

Equivalent to TSY / XGDY / SUBD #word / XGDY / TYS

GIVEX #word

Give (back) #word bytes of stack storage pointed to by X.

Equivalent to TSX / XGDX / ADDD #word / XGDX / TXS

GIVEY #word

Give (back) #word bytes of stack storage pointed to by Y.

Equivalent to TSY / XGDY / ADDD #word / XGDY / TYS

JCC addr16

Jump equivalent to BCC (BCS $+5 followed by JMP addr16)

JCS addr16

Jump equivalent to BCS (BCC $+5 followed by JMP addr16)

JEQ addr16

Jump equivalent to BEQ (BNE $+5 followed by JMP addr16)

JGE addr16

Jump equivalent to BGE (BLT $+5 followed by JMP addr16)

JGT addr16

Jump equivalent to BGT (BLE $+5 followed by JMP addr16)

JHI addr16

Jump equivalent to BHI (BLS $+5 followed by JMP addr16)

JHS addr16

Jump equivalent to BHS (BLO $+5 followed by JMP addr16)

JLE addr16

Jump equivalent to BLE (BGT $+5 followed by JMP addr16)

JLO addr16

Jump equivalent to BLO (BHS $+5 followed by JMP addr16)

JLS addr16

Jump equivalent to BLS (BHI $+5 followed by JMP addr16)

JLT addr16

Jump equivalent to BLT (BGE $+5 followed by JMP addr16)

JMI addr16

Jump equivalent to BMI (BPL $+5 followed by JMP addr16)

JNE addr16

Jump equivalent to BNE (BEQ $+5 followed by JMP addr16)

JPL addr16

Jump equivalent to BPL (BMI $+5 followed by JMP addr16)

JVC addr16

Jump equivalent to BVC (BVS $+5 followed by JMP addr16)

JVS addr16

Jump equivalent to BVS (BVC $+5 followed by JMP addr16)

CLS

Clear S flag:                                  PSHA / TPA / ANDA #$7F / TAP / PULA

CLX

Clear X flag:                                  PSHA / TPA / ANDA #$BF / TAP / PULA

PULL

Same as:                                        PULD / PULX / PULY

PUSH

Same as:                                        PSHY / PSHX / PSHD

SES

Set S flag:                                      PSHA / TPA / ORAA #$80 / TAP / PULA

SEX

Sign extend B to A:                    CLRA / TSTB / BPL ? / COMA / ?

WAIT

Enter WAIT mode:                      CLI / WAI

OS byteval

Operating system call:              SWI / DB byteval

OSW wordval

Operating system call:              SWI / DW wordval

XGXY

Exchange X and Y:                    XGDX / XGDY / XGDX


ASM11-generated Error and Warning Messages

 

This section provides the lists of error and warning messages.

 

Errors inform the user about problems that prevent the assembler from producing usable code.  If there is even a single error during assembly, no files will be created (except for the ERR file, if one was requested).

 

Warnings inform the user about problems that do not prevent the assembler from producing usable code but the code produced may not be what was intended, or it may be inefficient.   A program that has warnings may be totally correct and run as expected.

 

Errors and warnings that begin with ‘USER:’ are generated by #ERROR and #WARNING directives, respectively.  The source code author decides their meaning and importance.

 

In the lists below, what’s enclosed in angle brackets (< and >) is a ‘variable’ part of the message.  That is, it is different depending on the source line to which the error or warning refers.

 

The order the messages appear below is random.  Some messages have similar meanings; they simply result from different checks of the assembler.


E R R O R S

 

1.   Invalid binary number

The string following the % sign is not made up of zeros and/or ones.

2.   Binary number is longer than 16 bits