As with a lot of free software, the documentation is never complete. We're sure you'll find enough information here to effectively use ASHC11 as long as you've used some kind of assembler before.
Enhanced Expression Analysis - using simple left to right parsing with the addition of brackets allowing arbitrarily complex expressions to be created on a single assembly line. No complex hierarchy rules need be learnt. White space can be freely used to make expressions easier to analyse. Multiple formats are supported for different number base schemes (eg. 100B, or %100 are equivalent).
MACRO support has been added. Macros may have embedded definitions (ie. macros defined within another macro) and may call other macros (including themselves) from within the macro definition. LOCAL labels used to avoid symbol name clashes may be defined within macros. Compound arguments (ie. arguments containing embedded arguments) may be passed to macros. Early macro exit is possible with the EXITIF clause.
Repeat Blocks using REPT, IRPC and IRP can be declared. REPT blocks repeat a section of code a certain number of times. IRPC blocks repeat a block of code and iterate each pass with the next character from a supplied string. IRP is supplied with a list of arguments that are used successively for each iteration. LOCAL labels can also be used within repeat blocks.
Conditional Assembly is supported with the standard IF, ELSE, ENDIF construct. An ELSEIF clause allows more complex expressions to be expressed quite simply. An IFD and IFND adds a test for symbols being defined or not. Conditional expressions can be nested to many levels.
INCLUDE Files are supported to multiple levels with full listing support.
List Pseudo-ops and command line switches allow control over many variables including macro expansion listing, page length and width, title and subtitle, etc.
Alternative Opcodes have been defined such as EI for STI (or is that CLI? see what I mean?) and DI to enable and disable interrupts. All existing opcodes are supported but you can use more standard names like XOR, PUSH, POP, CALL, RET, JR, etc.
Compound Opcodes like PUSH D (PUSH A + PUSH B)
and POP D (POP B + POP A) have been added.
These enhancements have been made to allow easy migration from other processors,
and are designed to allow programmers to focus on the programming task rather than
on learning a new set of obscure and machine specific mnemonics.
ASHC11 Quick Start
ASHC11 is currently a 16 bit DOS program and is limited to 8.3 DOS filenames.
It is invoked from a DOS command prompt and reports errors directly to the console
for both pass 1 and pass 2. Here is its general invocation syntax.
C:\> ASHC11 sourcefilelist [-switchlist] |
ASHC11 file.ext |
ASHC11 x y -intel -listing |
Only an abbreviated form of each switch is required, eg, -l is enough to specify that a listing should be created. The minimum number of characters required for each switch is indicated by the upper case characters in the description below. Where a parameter is required the switch and the parameter should be separated with a colon (:), or an equals (=) sign. All switches must be separated with white space and the first switch is required to be proceeded by a hyphen. Subsequent switches may be optionally proceeded by a hyphen.
ASHC11 x -i l=list.lst |
SWITCH | EFFECT |
---|---|
Cycles | Displays the number of cycles for each instruction in the listing. this is currently not supported |
Errorlimit=count | Number of errors reported before aborting. Default is 20. |
Intel | Produce an Intel (or Intellec) HEX output file rather than the default Motorola S19 file. |
List [=filename] | Produce a listing file. The default filename is made up of the source files name and the extension .LST If the optional filename is supplied, that will be the full name of the listing file. |
Macrolist | List all macros used in the source code (goes at the end of the list file). |
Outfile=filename | Name of output file produced. Default is derived from the input file name and the type of output file requested (either S19 or HEX) |
P1list | The Pass 1 (one) switch forces a listing to be output to the console during pass one of the assembler's operation. This can be useful for debugging macros and repeat block that aren't working as you expect. |
Symbollist | The symbol table is appended to the list file. |
Timeinfo | Start time and end time information is sent to the console. |
Verbose | Displays additional information about the file(s) being processed. |
Xpand | Expands repeats and macros in the list file. Again useful for debugging. |
? | Force the basic help screen to be displayed. |
left_expr operator right_expr example: 3 + 7 left_expr operator (right_expr) example: 1 % (3 + 1)an expression is constructed like this:
expr ::= term operator term | eg. a + b term operator expr | eg. a + b / c term operator (expr) | eg. a + (b / c) expr operator expr eg. (a + d) / (b + c) operator ::= - | minus operator + | plus operator * | multiply operator / | divide operator (integer truncation) % | modulus operator (integer remainder) | | OR operator & | AND operator ^ | XOR (exclusive OR) << | left shift >> | right shift comparison ::= < | less than > | greater than >= | equal or greater than <= | equal or less than = | equal != not equal term ::= -term | (unary minus) ~term | (unary NOT or one's complement, 0->1, and 1->0) * | (the current PC) symbol | see the symbols section and labels and equates constant see next section
An expression list is simply a comma separated list of individual expressions, and is used for the definition of data storage. Macro parameter lists are also like expression lists. (all are described below).
expresion_list ::= expression, expression_list
constant ::= hex constant | binary constant | octal constant | decimal constant | ascii constant hex constant ::= ${hex digits} | {hex digits}H | {hex digits}h octal constant ::= {octal digits}Q | {octal digits}q | {octal digits}O | {octal digits}o binary constant ::= %{binary digits} | {binary digits}B | {binary digits}b decimal constant ::= decimal digits ASCII ::= any printing ASCII character ascii constant ::= '{ASCII character} | '{ASCII character}' ascii string ::= "{ASCII characters}" binary digits ::= 0 | 1 octal digits ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 decimal digits ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 hex digits ::= decimal digits | A | B | C | D | E | F
To distinguish symbols from the start of an expression or a constant, all symbols must begin with an upper or lower case alphabetic character, or one of the special characters, underscore (_), dot (.), question mark (?), or the "at" character (@). Numeric characters (ie. 0 through 9) and the dollar symbol ($) are allowed within the body of a symbol. Symbols may be up to at least 80 characters long (but symbol table space is finite) and all symbols are case sensitive (ie. symbol DELAY is NOT the same as Delay).
Note that some characters that are acceptable symbols for
Motorola's freeware assembler are not valid for ASHC11.
In particular, the dollar ($) symbol is NOT a valid
starting character for a symbol, although it may be used within the symbol.
Pseudo-Ops
Pseudo operation codes (called pseudo-ops) are directives to the assembler,
rather than real machine instructions
(machine instructions are also called operation codes,
or "opcodes" for short).
Pseudo-ops tell the assembler how to assemble the code,
as well as providing mechanisms to create data structures,
control listings, and other functions too.
Pseudo-ops may be in upper or lower case and can begin in any column other than the first. They may have a "." (dot) in front of them (to remain compatible with some other assemblers) so that ".eject" is the same as "eject" or "EJECT" or even ".Eject". Additionally, if a "#" (hash, or pound symbol) is in column one, it may be immediately followed by a pseudo-op. So that " include" is the same as "#include" (# is in the first column!).
For the purpose of describing them, pseudo-ops have been arbitrarily divided into the following alphabetically listed categories:
Following is an alphabetical listing of all recognised and actioned pseudo-ops.
More information on some is found in the section following this list.
Recognised Pseudo-Ops
= | A variable equate (it may be changed), equivalent to SET. See labels and equates. |
== | A fixed equate, equivalent to EQU. See labels and equates. |
align | Aligns the PC to the next modulo <expression> boundary. See data operations. |
alignz | As for ALIGN, but zero fills the space between. See data operations. |
auto | (not implemented in this release) See segment control. |
bss | See segment control. |
bsz | Block Storage of Zeros, Synonymous with ZMB. See data operations. |
code | Code is assembled in this segment. See segment control. |
data | Data is defined in this segment. See segment control. |
db | Define Byte(s). See data operations. |
ds | Define Storage. See data operations. |
dw | Define Word(s). See data operations. |
equ | A fixed equate (the same as ==) See labels and equates. |
eject | Places a page break in the output listing. See listing control. |
else | May follow IF or ELSEIF, and before ENDIF. See conditional expressions. |
elseif | Allows multiple conditions to be tested, like a SWITCH statement. See conditional expressions. |
end | See Ignored Pseudo-ops. |
endif | Completes an IFx/ELSEIF/ELSE statement. See conditional expressions. |
endm | Completes a MACRO definition block. See macros and repeat blocks. |
endr | Completes a REPT, IRPC, or IRP definition block. See macros and repeat blocks. |
EQU | Defines a fixed value that may not be redefined. See labels and equates. |
error | Produces a user defined error message during assembly. See errors and warnings. |
exitif | See macros and repeat blocks. |
fcb | Form Constant Byte(s). Synonymous with DB. See data operations. |
fcc | Form Constant Character(s). Is a subset of DB. See data operations. |
fdb | Form Double Byte(s). Synonymous with DW. See data operations. |
fill | Fills a section of memory with a constant expression. See data operations. |
if | Begins an IF expression and tests the expression for TRUE/FALSE. See conditional expressions. |
ifd | If Defined is a specific IF expression that tests if a variable is defined. See conditional expressions. |
ifnd | If Not Defined tests if a variable is NOT defined. The converse if IFD. See conditional expressions. |
include | Allows source code to have references to other source files. See include files. |
irp | Iterated Repeat. A section of code is iterated for various arguments. See macros and repeat blocks. |
irpc | Iterated Repeat for a Character argument. See macros and repeat blocks. |
list | Turns on listing output. See listing control. |
local | Defines local labels within MACRO, IRP, IRPC and REPT blocks. See macros and repeat blocks. |
macro | A collection of source lines that are invoked by "calling it up". See macros and repeat blocks. |
name | See ignored pseudo-ops. |
nolist | Turns off listing output. See listing control. |
org | Sets the PC, or location counter to a specific value. See segments. |
page | Defines page width and length and optionally specifies an EJECT. See listing control. |
pagelength | Specifies the maximum length in lines of each listing page. See listing control. |
pagewidth | Specifies the maximum width of the listing in characters. See listing control. |
ram | Declares uninitialised data. See segment control. |
rept | Defines lines of source that will be repeated a number of times. See macros and repeat blocks. |
rmb | Reserve Memory Byte(s). Allocates storage space. See data operations. |
set | Defines a variable equate. Synonymous with =. See labels and equates. |
spc | See Ignored Pseudo-op. |
subtitle | Declares a subtitle shown on the listing page. See listing control. |
title | Declares a title shown on the listing page. See listing control. |
warning | Produces a user defined warning message during assembly. See errors and warnings. |
zmb | Zero Memory Bytes. Synonymous with BSZ. See data operations. |
IF <expr> ... ENDIF |
DEBUG equ 3 IF DEBUG >= 2 ;Assemble if symbol DEBUG is >= to 2 ldd MSG ;This will be assembled in this example call MSGOUT ENDIF ;This terminates the conditional section of code |
IFD <symbolname> ... ;assembles if <symbolname> IS defined ENDIF IFND <symbolname> ... ;assembles if <symbolname> is NOT defined ENDIF |
IFND PRINTF ;Tests if symbol PRINTF is defined INCLUDE "printf.inc" ;it's not so include the definitions ENDIF |
Here is an example where the ELSE statement's code will be assembled.
J = 5 IF J < 4 ;so this is NOT true DB $01 ;this is NOT assembled ELSE DB $02 ;this will be assembled ENDIF |
IFx <expr or symbol> ;IFx may be IF, IFD or IFND ... ELSEIF <expr> ... ELSEIF <expr> ;optional multiple ELSEIF clause ... ELSE ;optional ELSE clause ... ENDIF |
Here is an example where two ELSEIF code sections would evaluate true, but only the first will generate code.
K = 2 IF K > 2 ;NOT true ldaa #K ;NOT assembled ELSEIF K = 2 ;IS true ldaa VAR1 ;IS assembled ELSEIF K < 3 ;IS true but NOT assembled as we already matched TRUE ldaa VAR2 ;NOT assembled ELSE ;ignored as we already have a TRUE match ldaa #4 ;NOT assembled ENDIF ;completes this IF block |
IF A = B IF C >= D dw C + D ELSE ;ELSE clause for "IF C >= D" dw D - C ENDIF ;terminates the "IF C >= D" expression ELSE ;ELSE clause for "IF A = B" dw $123 ENDIF ;terminates the "IF A = B" expression |
Note that ALIGN <expr> advances the PC by PC % <expr> (ie. the remainder when the PC is divided by <expr>. Some assemblers call this directive EVEN.
ALIGNZ <expr> works like ALIGN but explicitly sets the skipped bytes to zero.
BSZ <expr>
BSZ means Block Size Zeroed and defines a block of memory of size <expr> set to zeros.
Also called ZMB (Zeroed Memory Bytes)
DB <expr> [[, <expr>]..]
Define Byte(s) sets memory to the value of the expression <expr>.
Single values, of any given radix base, may be defined.
Single characters are defined by enclosing them in single quotes.
Strings may also be defined by enclosing them within double quotes.
Multiple comma separated values may be defined on the one line.
DB $12 ;hex byte DB %10001101 ;binary byte DB 'C' ;character ('C) also works DB "text" ;double quoted text DB 10, $ff, %1011001, 'A', "string", 0 ;multiple format too... |
All lables must start in the first column (otherwise they will be interpreted as a pseudo-op) and may optionally be terminated with one or more colons (ie. :, or ::, etc.) the colon(s) are not considered part of the label.
Local labels begin with the at symbol (@) and are followed by one or more digits,
and are used between normal (ie. non-local) labels when it's not convenient to
define a unique identifier.
Local labels are checked at assembly time to ensure they are not duplicated,
and that their scope does not cross a "symbol boundary".
EQU, = =
The equate or double equals sign (= =,
there is no space between the two equals symbols)
is used to define a symbol with a fixed value, as follows:
symbolname equ expression anothername == another+expression |
counter set 25 counter = counter+1 |
Here's an example of a page from a list file showing the page's header block, and a number of selected lines of the source file (the ... indicates where lines have been removed):
ASHC11, 68HC11 Macro Assembler v1.2 (c) Copyright 2000 Tech Edge Pty. Ltd. page 2 - amxy.a - Fri 1 Sep 2000 10:58:09.45 Re-assembly of AMXY.BIN =005d 112 kProgramID == $5D ;$5D for AMXY 113 114 #include "macs.a" ... 250 KKPGMID ;($c008) Program ID c008 5d 251 db kProgramID ;$5d in AMXY ... d081 86 60 1522 ldaA #$60 ;Read AN6 d083 bd ec d8 1523 call ReadADC ;Read fuel pump voltage |
The number of lines listed per page is controlled by the pagelength parameter, and the default is to have a single page (ie. no page breaks in the list file). A page length of zero (0) will restore the default of a single page. Alternatively, you can use the pagelength pseudo-op.
The number of character columns on each list page is controlled by the
pagewidth parameter. A maximum of 255 columns will be listed in the output.
All characters beyond pagewidth will simply be truncated.
Note that you can specify the page width independently of the page length by
using a null pagelength parameter and a comma (,)
before the pagewidth parameter.
Alternatively, you can use the pagewidth pseudo-op.
PAGELENGTH <pagelength>
Both pagelength and pagewidth pseudo-ops are used in an obvious
manner and have the same effect as the corresponding
pagewidth and pagelength parameters to the page pseudo-op described above.
PAGEWIDTH <pagewidth>SUBTITLE <text>
By default, on each page of the list file,
there are two blank lines following the standard two lines of header information.
All text following the title pseudo-op is placed on the first of these lines.
All text following the subtitle pseudo-op is placed on the second of these lines.
TITLE <text>Macros and Repeat Blocks
Macros and repeat blocks include the pseudo-ops
exitif, irp, irpc, local, macro,
rept, endm, endr.
The following sections describe each pseudo-op.
Macros:
Macros allow a piece of code to be defined once and then invoked by
simply writing the macro’s name along with any arguments defined for the macro.
This aids the construction of complex and correct code by eliminating typing errors
as a major cause of programmer error.
It also allows a programmer to define easily reusable sections of code,
speeding up future tasks.
<name> MACRO [[, <param>] ..]
MACRO <name> [[, <param>] ..]
ENDM
Here’s a simple parameterless macro definition defined with the MACRO keyword and terminated with the ENDM keyword.
setflag MACRO ;declare macro "setflag" ldab #1 ;set B register to 1 stab flag ;set the variable called flag ENDM |
setflag ;invoke macro example called "setflag" |
ldab #1 stab flag |
MACRO setflag ;also declares macro "setflag" |
Typically a macro will be used with parameters to vary how it is expanded. The macro’s parameters are declared to the right of the MACRO pseudo-op, and if there is more than one parameter then they must be comma separated. An example using two parameter fields, "here" and "value", follows.
setvar MACRO here, value ldab #value ;set B with immediate value "value" stab here ;store B into location "here" ENDM |
Each occurrence of "here" and "value" in the macro’s definition will be replaced with the arguments supplied with the macro. This macro is invoked three times below, along with two arguments for each invocation:
setvar loc1, 1 ;set variable "loc1" to immediate value 1 setvar loc2, 2 ;set loc2 to 2 setvar $124, 'X' ;set $124 to ASCII 'X' |
The first two invocation of setvar will produce the code:
ldab #1 ;'value' is substituted with parameter '1' stab loc1 ;'here'is substituted with the parameter 'loc1' ldab #2 ;'value' is substituted with parameter '2' stab loc2 ;'here'is substituted with the parameter 'loc2' |
Repeat Blocks are used to define sections of code that are to be repeated and/or iterated a number of times. The REPT pseudo-op simply repeats a block of code a certain number of times. Here’s a REPT block that initialises a data area. Defining a REPT block is like defining a macro, but the REPT block is immediately actioned and is not saved for future use.
REPT 10 ;repeat the next code section 10 times db 'A' ;define a single byte 'A' ENDR ;end of REPT block |
The above REPT block produces the equivalent of the following code (although the listing would show 10 individual db ‘A’ instructions).
db "AAAAAAAAAA" |
IRPC chr, "JKLMNOP" db 'chr' ;chr will take on the values J, K, L, etc. ENDR |
The above IRPC produces the following code
db 'J' db 'K' … db 'P'. |
IRP is slightly more complex and uses a (comma separated) list of values to be substituted, as the following example shows (see example file "x3"):
IRP param, $20, $31, $82 dw param ;param will take the values $20, then $31, … ENDR |
dw $20 dw $31 dw $82 |
More complex code structures are possible by combining REPT or IRPx with one or more macros. Here’s an example that uses IRPC to set up a data area invocation (see example file "x4") First we define a macro, then a repeat block using that macro:
defchar MACRO chr Lchr db 'chr' ;define a label and a data byte ENDM IRPC _ch, <ABCD> defchar _ch ENDR |
defchar A defchar B defchar C defchar D |
LA db 'A' ;Label LA for data byte "A" LB db 'B' ;etc.. LC db 'C' LD db 'D' |
Macro expansion can be prematurely terminated with exitif if the expression evaluates to a non-zero value.
The local pseudo-op defines local lables that have a scope only within
the current macro or repeat block.
Note that bss selects the same segment as data (some compilers use this name)
and the auto segment is the fourth independent segment, and you can
use this any way you like.
Tech Edge does not warrant ASHC11 for any use what so ever.
You use ASHC11 at your own risk.
Only eight dot three (8.3) file names are recognised by ASHC11.
This means you may have to use these funny ~ symbols in file names.
I may change ASHC11 to use far pointer logic within symbol table processing
to improve the number of labels that may be defined.
I appreciate all reports of bugs you find.
Send them to me
and I'll try and fix it for everyone ASAP.
segment control
ORG <expr>
Is used to set the PC to the expression following.
AUTO, BSS, CODE, DATA & RAM
Segments are predefined names for four different areas within your source code.
The PC may be independently set for each segment (using org), and when you change segments,
the PC will automatically be set to that segment's last used value.
code and data segments can be used in obvious ways when
you'd like to separate code and data areas that end up in an EPROM.
ram is used for RAM data that will be stored in volatile memory.
Disclaimer, Bugs, Limitations, Enhancements
This version of ASHC11 is provided free, however
ASHC11 is Copyright © Tech Edge Pty. Ltd. and you may not use it
for any commercial development without the written consent of Tech Edge.
Bugs
There are no serious bugs that I know of.
The most complex part of ASHC11 is the macro processing code
which amounts to over half the source code that generates assembler output.
I have had random occasional failures when using complex and convoluted test scripts.
This indicates that perhaps there are some improperly initialised variables that
still need to be tracked down.
I'm happy however that ASHC11 is stable for the level of macro
complexity that the majority of users will code.
Limitations
ASHC11's potentially biggest limitation is that it's a 16 bit DOS program
that I have constrained to a small model in order to minimise its
program size and maximise it execution speed.
The immediate implication is that symbol table space (including macro
definition space) is limited to 64 kbytes less the code size of ASHC11 itself.
Desipte this, some thousands of "normal" sized symbols may defined.
Enhancements
Macros may be called with parameters that are themselves lists of parameters.
This is done by enclosing parameters within < and > brackets.
This can be a very powerful facility, and when I have removed all of the bugs
in this part of macro processing, I'll update ASHC11 and the documentation
to describe how it works.
For the moments however you should assume this feature doesn't work.
The reason I mention this feature here is so you understand possible strange behaviour
when you use < & > within macro argument expressions.
Different Mnemonics
The following mnemonics are accepted by ASHC11, they are compared
with those as specified by Motorola.
ASHC11 Mnemonics Motorola's Function Performed
call JSR Call
callr BSR Call Relative (short call)
cmpD, cmpX cmpY CP? Compare (16 bit register)
decX, decY, decS DE? Decrement (16 bit register)
di SEI Disable Interrupts
ei CLI Enable Interrupts
incX, incY, incS IN? Increment (16 bit register)
jr BRA Jump Relative (short jump)
push, pushB, pushX, pushY PSH? Push on to stack
popA, popB, popX, popY PUL? Pop off stack
ret RTS Return (from subroutine)
reti RTI Return From Interrupt
xorA, xorB EOR? eXclusive Or
Why I wrote the ASHC11 Macro Assembler
When faced with a fairly simple project requiring a 68HC11 assembler,
I readily obtained a freeware assembler.
This tool almost did what I wanted.
It certainly assembled, and I obtained some HEX output I could blow
into an EPROM and test out on my board.
But then the problems started.
Why didn't my code do what I expected?
It was really quite simple.
The assembler was not telling me I had simple syntax errors,
and was assuming I meant something else.
I was very upset, but not discouraged, so I looked for another assembler. To cut a long story short, I looked and looked for quite some time before I came to the conclusion there was nothing that gave me all the features I needed. Time to write my own assembler, with the features I wanted.
I started with the source for Motorola's freeware assembler,
but quickly replaced all of the code,
leaving just the tables that define the opcodes.
I eventually replaced even these tables.
I ended up with a generic assembler with lots of features,
and a 68HC11 specific assembler that adds even more features.
Statistics by www.digits.com
Shows approximate hits since 1 Sept 2000.
Home | ASHC11 Feedback | Copyright