a high level macro cross assembler for 6502

(C)Copyright 1987,1988 Matthew Dillon, All Rights Reserved
Modified by Peter King for the Scholar programme of Heriot-Watt University



	dasm srcfile [options]


select output file name
select list file name (else none generated)
select symbol dump file name (else none generated)
select verboseness 0-4 (default 0, see below)


    dasm master.asm -omaster.bin -lmaster.lst -v3


  • 0 (default) Only warnings and errors are generated
  • 1
  • 2 mismatches between program labels and equates are displayed on every pass (usually none occur in the first pass unless you have re-declared a symbol name).
    	displayed information for symbols:
    	    ???? = unknown value
    	    str  = symbol is a string
    	    eqm  = symbol is an eqm macro
    	    (r)  = symbol has been referenced
    	    (s)  = symbol created with SET or EQM pseudo-op
  • 3 Unresolved and unreferenced symbols are displayed every pass (unsorted, sorry)
  • 4 An entire symbol list is displayed every pass to STDOUT. (unsorted, sorry)

    The SEG pseudo-op creates/sets the current segment. Each segment has it's own origin and is optionally an `uninitialized' segment. Uninitialized segments produce no output and have no restrictions. This is useful for determining the size of a certain assembly sequence without generating code, and for assigning RAM to labels.

    'Initialized' segments produce output. The following should be considered when generating code:

    1. The default fill character when using ORG to skip forward is 00. This is a GLOBAL default and effects all segments. See ORG.
    2. The default fill character for DS is 00 and is independent of the default fill character for ORG (see DS).


    Most everything is recursive. You cannot have a macro DEFINITION within a macro definition, but can nest macro calls, repeat loops, and include files.

    The other major feature in this assembler is the SUBROUTINE pseudo-op, which logically separates local labels (starting with a dot). This allows you to reuse label names (for example, .1 .fail) rather than think up crazy combinations of the current subroutine to keep it all unique. Almost nothing need be resolved in pass 1. The assembler will make multiple passes in an attempt to resolve the assembly (including just one pass if everything is resolved immediately).


    INCLUDE "name"
    Include another assembly file.
    [label] SEG[.U] name
    This sets the current segment, creating it if necessary. If a .U extension is specified on segment creation, the segment is an UNINITIALIZED segment. The .U is not needed when going back to an already created uninitialized segment, though it makes the code more readable.
    [label] DC[.BWL] exp,exp,exp ...
    Declare data in the current segment. No output is generated if within a .U segment. Note that the byte ordering for the selected processor is used for each entry.

    The default size extension is a byte.

    [label] DS[.BWL] exp[,filler]

    declare space (default filler is 0). Data is not generated if within an uninitialized segment. Note that the number of bytes generated is exp * entrysize (1,2, or 4)

    The default size extension is a byte.

    Note that the default filler is always 0 (has nothing to do with the ORG default filler).

    [label] DV[.BWL] eqmlabel exp,exp,exp....

    This is equivalent to DC, but each exp in the list is passed through the symbolic expression specified by the EQM label. The expression is held in a special symbol dotdot '..' on each call to the EQM label.

    See EQM below

    [label] HEX hh hh hh..
    This sets down raw HEX data. Spaces are optional between bytes. NO EXPRESSIONS are allowed. Note that you do NOT place a $ in front of the digits. This is a short form for creating tables compactly. Data is always laid down on a byte-by-byte basis.
    	    Example:	    HEX 1A45 45 13254F 3E12
    Abort assembly.
    [label] ORG exp[,DefaultFillVal]
    This pseudo-op sets the current origin. You can also set the global default fill character (a byte value) with this pseudo-op. NOTE that no filler is generated until the first data-generating opcode/pseudo-op is encountered after this one. Sequences like:
    	org  0,255
    	org  100,0
    	org  200
    	dc   23
    will result in 200 zero's and a 23. This allows you to specify some ORG, then change your mind and specify some other (lower address) ORG without causing an error (assuming nothing is generated in between).

    Normally, DS and ALIGN are used to generate specific filler values.

    [label] RORG exp
    This activates the relocatable origin. All generated addresses, including '.', although physically placed at the true origin, will use values from the relocatable origin. While in effect both the physical origin and relocatable origin are updated.

    The relocatable origin can skip around (no limitations). The relocatable origin is a function of the segment. That is, you can still SEG to another segment that does not have a relocatable origin activated, do other (independent) stuff there, and then switch back to the current segment and continue where you left off.

    ECHO exp,exp,exp
    The expressions (which may also be strings), are echoed on the screen and into the list file
    [label] REND
    Deactivate the relocatable origin for the current segment. Generation uses the real origin for reference.
    [label] ALIGN N[,fill]
    Align the current PC to an N byte boundary. The default fill character is always 0, and has nothing to do with the default fill character specifiable in an ORG.
    [label] SUBROUTINE name
    This isn't really a subroutine, but a boundary between sets of temporary labels (which begin with a dot). Temporary label names are unique within segments of code bounded by SUBROUTINE:
    		CHARLIE subroutine
    			ldx #10
    		.1	dex
    			bne .1
    		BEN	subroutine
    			ldx #20
    		.qq	dex
    			bne .qq
    Automatic temporary label boundaries occur for each macro level. Usually temporary labels are used in macros and within actual subroutines (so you don't have to think up a thousand different names)
    symbol EQU exp
    The expression is evaluated and the result assigned to the symbol.
    symbol EQM exp
    The STRING representing the expression is assigned to the symbol. Occurrences of the label in later expressions causes the string to be evaluated for each occurrence. Also used in conjunction with the DV psuedo-op.
    symbol SET exp
    Same as EQU, but the symbol may be reassigned later.
    MAC name
    Declare a macro. lines between MAC and ENDM are the macro. You cannot recursively declare a macro. You CAN recursively use a macro (reference a macro in a macro). No label is allowed to the left of MAC or ENDM.

    Arguments passed to macros are referenced with: {#}. The first argument passed to a macro would thus be {1}. You should always use LOCAL labels (.name) inside macros which you use more than once. {0} represents an EXACT substitution of the ENTIRE argument line.

    end of macro definition. NO LABEL ALLOWED ON THE LEFT!
    Used in conjunction with conditionals. Exits the current macro
    [label] IFCONST exp
    Is TRUE if the expression result is defined, FALSE otherwise and NO error is generated if the expression is undefined.
    [label] IFNCONST exp
    Is TRUE if the expression result is undefined, FALSE otherwise and NO error is generated if the expression is undefined.
    [label] IF exp
    Is TRUE if the expression result is defined AND non-zero. Is FALSE if the expression result is defined AND zero. Neither IF or ELSE will be executed if the expression result is undefined. If the expression is undefined, another assembly pass is automatically taken.
    [label] ELSE
    ELSE the current IF.
    [label] ENDIF
    [label] EIF
    Terminate an IF. ENDIF and EIF are equivalent.
    [label] REPEAT exp
    [label] REPEND
    Repeat code between REPEAT/REPEND 'exp' times. if exp == 0, the code repeats forever. exp is evaluated once.
    	Y   SET     0
    	    REPEAT  10
    	X   SET     0
    	    REPEAT  10
    	    DC	    X,Y
    	X   SET     X + 1
    	Y   SET     Y + 1
    generates an output table: 0,0 1,0 2,0 ... 9,0 0,1 1,1 2,1 ... 9,1, etc...

    Labels within a REPEAT/REPEND should be temporary labels with a SUBROUTINE pseudo-op to keep them unique.

    The Label to the left of REPEND is assigned AFTER the loop FINISHES.

    [label] XXX[.force] operand
    XXX is some mnemonic, not necessarily three characters long. The .FORCE optional extension is used to force specific addressing modes (see below).


    The label will be set to the current ORG/RORG either before or after a pseudo-op is executed. Most of the time, the label to the left of a pseudo-op is the current ORG/RORG. The following pseudo-ops labels are created AFTER execution of the pseudo-op:



    The assembler may have to make several passes through the source code to resolve all generation. The number of passes is not limited to two. Since this may result in an unexpected, verbose option 2, 3, and 4 have been provided to allow determination of the cause. The assembler will give up if it thinks it can't do the assembly in *any* number of passes.

    Error reporting could be better....


    [] may be used to group expressions. The precedence of operators is the same as for the C language in almost all respects. Use brackets [] when you are unsure. The reason () cannot be used to group expressions is due to a conflict with the 6502 and other assembly languages.

    Some operators, such as ||, can return a resolved value even if one of the expressions is not resolved. Operators are as follows:

    NOTE WELL! Some operations will result in non-byte values when a byte value was wanted. For example: ~1 is NOT $FF, but $FFFFFFFF. Preceding it with a < (take LSB of) will solve the problem. ALL ARITHMETIC IS CARRIED OUT IN 32 BITS. The final Result will be automatically truncated to the maximum that can be handled by the particular machine language (usually a word) when applied to standard mnemonics.

    	prec	    UNARY
    	20  ~exp    one's complement.
    	20  -exp    negation
    	20  !exp    not expression (returns 0 if exp non-zero, 1 if exp zero)
    	20  <exp    take LSB byte of a 16 bit expression
    	20  >exp    take MSB byte of an expression
    	19  *	    multiplication
    	19  /	    division
    	19  %	    mod
    	18  +	    addition
    	18  -	    subtraction
    	17  >>,<<   shift right, shift left
    	16  >,>=    greater, greater equal
    	16  <,<=    smaller, smaller equal
    	15  ==	    equal to.  Try to use this instead of =
    	15  =	    exactly the same as == (exists compatibility)
    	15  !=	    not equal to
    	14  &	    logical and
    	13  ^	    logical xor
    	12  |	    logical or
    	11  &&	    left expression is true AND right expression is true
    	10  ||	    left expression is true OR right expression is true
    	 9  ?	    if left expression is true, result is right expression,
    		    else result is 0.	[10 ? 20] returns 20
    	 8  []	    group expressions
    	 7  ,	    separate expressions in list (also used in
    		    addressing mode resolution, BE CAREFUL!
    	nnn	decimal
    	0nnn	octal
    	%nnn	binary
    	$nnn	hex
    	'c      character
    	"cc.."  string (NOT zero terminated if in DC/DS/DV)
    	[exp]d	the constant expressions is evaluated and it's decimal
    		result turned into an ASCII string.
    	...	-holds CHECKSUM so far (of actual-generated stuff)
    	..	-holds evaluated value in DV pseudo-op
    	.name	-represents a temporary symbol name.  Temporary symbols
    		 may be reused inside MACROS and between SUBROUTINES, but
    		 may not be referenced across macros or across SUBROUTINEs.
    	.	-current program counter (as of the beginning of the
    	name	-beginning with an alpha character and containing letters,
    		 numbers, or '_'.  Represents some global symbol name.

    WHY codes:

    Each bit in the WHY word (verbose option 1) is a reason (why the assembler needs to do another pass), as follows:

        bit 0   expression in mnemonic not resolved
    	1   -
    	2   expression in a DC not resolved
    	3   expression in a DV not resolved (probably in DV's EQM symbol)
    	4   expression in a DV not resolved (could be in DV's EQM symbol)
    	5   expression in a DS not resolved
    	6   expression in an ALIGN not resolved
    	7   ALIGN: Relocatable origin not known (if in RORG at the time)
    	8   ALIGN: Normal origin not known	(if in ORG at the time)
    	9   EQU:   expression not resolved
    	10  EQU:   value mismatch from previous pass (phase error)
    	11  IF:     expression not resolved
    	12  REPEAT: expression not resolved
    	13  a program label has been defined after it has been
    	    referenced (forward reference) and thus we need another
    	14  a program label's value is different from that of the
    	    previous pass (phase error)

    Certain errors will cause the assembly to abort immediately, others will wait until the current pass is over before terminating assembly. All remining types of error allow another pass to occur in the hopes the error will fix itself.