~ndiddy/a65

31a8a450b4c61ee817add539953dc03da3404d2d — Nathan Misner 4 months ago 1587479
converted manual to html
4 files changed, 657 insertions(+), 1266 deletions(-)

D A65.DOC
A a65.html
M a65util.c
M readme.txt
D A65.DOC => A65.DOC +0 -1262
@@ 1,1262 0,0 @@
/*
	HEADER:		CUG129;
	TITLE:		6502/65C02 Cross-Assemblers;
	FILENAME:	A65.DOC;
	VERSION:	0.1;
	DATE:		08/27/1988;

	DESCRIPTION:	"These programs let you use your computer to assemble
			code for the MOS Technology 6502 and Rockwell 65C02
			microprocessors.  The program is written in portable
			C rather than BDS C.  All assembler features are
			supported except relocation, linkage, and macros.";

	KEYWORDS:	Software Development, Assemblers, Cross-Assemblers,
			MOS Technology, Rockwell, 6502, 65C02;

	SYSTEM:		CP/M-80, CP/M-86, HP-UX, MSDOS, PCDOS, QNIX;
	COMPILERS:	Aztec C86, Aztec CII, Eco-C, HP-UX, Microsoft C,
			QNIX C;

	WARNINGS:	"HP-UX is a Berkeley 4.2 UNIX look-alike, so the port
			to UNIX should be trivial.  So far, the program
			compiles under two different MSDOS/PCDOS compilers, so
			the port to other MSDOS/PCDOS compilers should be
			easy.";

	AUTHORS:	William C. Colley III;
*/














                           6502/65C02 Cross-Assemblers


                                   Version 0.1


                    Copyright (c) 1986 William C. Colley, III






                            The manual such as it is.











        Legal Note:    This package may be used for any commercial or 
                       non-commercial purpose.  It may be copied and 
                       distributed freely provided that any fee charged 
                       by the distributor of the copy does not exceed the 
                       sum of:  1) the cost of the media the copy is 
                       written on,  2) any required costs of shipping the 
                       copy, and  3) a nominal handling fee.  Any other 
                       distribution requires the written permission of 
                       the author.  Also, the author's copyright notices 
                       shall not be removed from the program source, the 
                       program object, or the program documentation.














                                Table of Contents

        1.0  How to Use the Cross-Assembler Package ..................  3
        2.0  Format of Cross-Assembler Source Lines ..................  4
             2.1  Labels .............................................  5
             2.2  Numeric Constants ..................................  5
             2.3  String Constants ...................................  6
             2.4  Expressions ........................................  6
        3.0  Machine Opcodes .........................................  7
        4.0  Pseudo Opcodes ..........................................  9
             4.1  Pseudo-ops -- END ..................................  9
             4.2  Pseudo-ops -- EQU .................................. 10
             4.3  Pseudo-ops -- FCB .................................. 10
             4.4  Pseudo-ops -- FCC .................................. 10
             4.5  Pseudo-ops -- FDB .................................. 11
             4.6  Pseudo-ops -- IF, ELSE, ENDI ....................... 11
             4.7  Pseudo-ops -- INCL ................................. 12
             4.8  Pseudo-ops -- ORG .................................. 12
             4.9  Pseudo-ops -- PAGE ................................. 12
             4.10 Pseudo-ops -- RMB .................................. 13
             4.11 Pseudo-ops -- SET .................................. 13
             4.12 Pseudo-ops -- TITL ................................. 13
        5.0  Assembly Errors ......................................... 13
             5.1  Error * -- Illegal or Missing Statement ............ 14
             5.2  Error ( -- Parenthesis Imbalance ................... 14
             5.3  Error " -- Missing Quotation Mark .................. 14
             5.4  Error A -- Illegal Addressing Mode ................. 14
             5.5  Error B -- Branch Target Too Distant ............... 14
             5.6  Error D -- Illegal Digit ........................... 14
             5.7  Error E -- Illegal Expression ...................... 15
             5.8  Error I -- IF-ENDI Imbalance ....................... 15
             5.9  Error L -- Illegal Label ........................... 15
             5.10 Error M -- Multiply Defined Label .................. 15
             5.11 Error O -- Illegal Opcode .......................... 15
             5.12 Error P -- Phasing Error ........................... 16
             5.13 Error R -- Illegal Register ........................ 16
             5.14 Error S -- Illegal Syntax .......................... 16
             5.15 Error T -- Too Many Arguments ...................... 16
             5.16 Error U -- Undefined Label ......................... 16
             5.17 Error V -- Illegal Value ........................... 16
        6.0  Warning Messages ........................................ 17
             6.1  Warning -- Illegal Option Ignored .................. 17
             6.2  Warning -- -l Option Ignored -- No File Name ....... 17
             6.3  Warning -- -o Option Ignored -- No File Name ....... 17
             6.4  Warning -- Extra Source File Ignored ............... 17
             6.5  Warning -- Extra Listing File Ignored .............. 17
             6.6  Warning -- Extra Object File Ignored ............... 17
        7.0  Fatal Error Messages .................................... 17
             7.1  Fatal Error -- No Source File Specified ............ 17
             7.2  Fatal Error -- Source File Did Not Open ............ 18
             7.3  Fatal Error -- Listing File Did Not Open ........... 18
             7.4  Fatal Error -- Object File Did Not Open ............ 18
             7.5  Fatal Error -- Error Reading Source File ........... 18
             7.6  Fatal Error -- Disk or Directory Full .............. 18
             7.7  Fatal Error -- File Stack Overflow ................. 18



                                        1



             7.8  Fatal Error -- If Stack Overflow ................... 18
             7.9  Fatal Error -- Too Many Symbols .................... 18























































                                        2



        1.0  How to Use the Cross-Assembler Package

             First, the question, "What does a cross-assembler do?" needs 
        to be addressed as there is considerable confusion on this point.  
        A cross-assembler is just like any other assembler except that it 
        runs on some CPU other than the one for which it assembles code.  
        For example, this package assembles 6502 or 65C02 source code 
        into 6502 or 65C02 object code, but it runs on an 8080, a Z-80, 
        an 8088, or whatever other CPU you happen to have a C compiler 
        for.  The reason that cross-assemblers are useful is that you 
        probably already have a CPU with memory, disk drives, a text 
        editor, an operating system, and all sorts of hard-to-build or 
        expensive facilities on hand.  A cross-assembler allows you to 
        use these facilites to develop code for a 6502 or 65C02.

        This program requires one input file (your 6502 or 65C02 source 
        code) and zero to two output files (the listing and the object).  
        The input file MUST be specified, or the assembler will bomb on a 
        fatal error.  The listing and object files are optional.  If no 
        listing file is specified, no listing is generated, and if no 
        object file is specified, no object is generated.  If the object 
        file is specified, the object is written to this file in "Intel 
        hexadecimal" format.

             The command line for the 6502 cross-assembler looks like 
        this:

                  A65 source_file { -l list_file } { -o object_file }

        where the { } indicates that the specified item is optional.

             Some examples are in order:

             a65 test65.asm                          source:   test65.asm
                                                     listing:  none
                                                     object:   none

             a65 test65.asm -l test65.prn            source:   test65.asm
                                                     listing:  test65.prn
                                                     object:   none

             a65 test65.asm -o test65.hex            source:   test65.asm
                                                     listing:  none
                                                     object:   test65.hex

             a65 test65.asm -l test65.prn -o test65.hex
                                                     source:   test65.asm
                                                     listing:  test65.prn
                                                     object:   test65.hex

             The order in which the source, listing, and object files are 
        specified does not matter.  Note that no default file name exten-
        sions are supplied by the assembler as this gives rise to porta-
        bility problems.




                                        3



             The 65C02 cross assembler works the same way except that the 
        command is "a65c" instead of "a65".


        2.0  Format of Cross-Assembler Source Lines

             The source file that the cross-assembler processes into a 
        listing and an object is an ASCII text file that you can prepare 
        with whatever editor you have at hand.  The most-significant 
        (parity) bit of each character is cleared as the character is 
        read from disk by the cross-assembler, so editors that set this 
        bit (such as WordStar's document mode) should not bother this 
        program.  All printing characters, the ASCII TAB character ($09), 
        and newline character(s) are processed by the assembler.  All 
        other characters are passed through to the listing file, but are 
        otherwise ignored.

             The source file is divided into lines by newline char-
        acter(s).  The internal buffers of the cross-assembler will 
        accommodate lines of up to 255 characters which should be more 
        than ample for almost any job.  If you must use longer lines, 
        change the constant MAXLINE in file A65.H or A65C.H and recompile 
        the cross-assembler.  Otherwise, you will overflow the buffers, 
        and the program will mysteriously crash.

             Each source line is made up of three fields:  the label 
        field, the opcode field, and the argument field.  The label field 
        is optional, but if it is present, it must begin in column 1.  
        The opcode field is optional, but if it is present, it must not 
        begin in column 1.  If both a label and an opcode are present, 
        one or more spaces and/or TAB characters must separate the two.  
        If the opcode requires arguments, they are placed in the argument 
        field which is separated from the opcode field by one or more 
        spaces and/or TAB characters.  Finally, an optional comment can 
        be added to the end of the line.  This comment must begin with a 
        semicolon which signals the assembler to pass the rest of the 
        line to the listing and otherwise ignore it.  Thus, the source 
        line looks like this:

             {label}{ opcode{ arguments}}{;commentary}

        where the { } indicates that the specified item is optional.

             Some examples are in order:

          column 1
             |
             v
             GRONK   LDA   OFFSET, X       ; This line has everything.
                     STA   MAILBOX         ; This line has no label.
             BEEP                          ; This line has no opcode.
             ; This line has no label and no opcode.

             ; The previous line has nothing at all.
                     END                   ; This line has no argument.



                                        4



        2.1  Labels

             A label is any sequence of alphabetic or numeric characters 
        starting with an alphabetic.  The legal alphabetics are:

                    ! & , . : ? [ \ ] ^ _  ` { | }  ~  A-Z  a-z

        The numeric characters are the digits 0-9.  Note that "A" is not 
        the same as "a" in a label.  This can explain mysterious U 
        (undefined label) errors occurring when a label appears to be 
        defined.

             A label is permitted on any line except a line where the 
        opcode is IF, ELSE, or ENDIF.  The label is assigned the value of 
        the assembly program counter before any of the rest of the line 
        is processed except when the opcode is EQU, ORG, or SET.

             Labels can have the same name as opcodes, but they cannot
        have the same name as operators or registers.  The reserved 
        (operator and register) names are:

             A         AND       EQ        GE        GT        HIGH
             LE        LT        LOW       MOD       NE        NOT
             OR        SHL       SHR       X         XOR       Y

             If a label is used in an expression before it is assigned a 
        value, the label is said to be "forward-referenced."  For 
        example:

             L1   EQU  L2 + 1   ; L2 is forward-referenced here.
             L2
             L3   EQU  L2 + 1   ; L2 is not forward-referenced here.


        2.2  Numeric Constants

             Numeric constants can be formed in two ways:  the Intel 
        convention or the Motorola convention.  The cross-assembler 
        supports both.

             An Intel-type numeric constant starts with a numeric 
        character (0-9), continues with zero or more digits (0-9, A-F), 
        and ends with an optional base designator.  The base designators 
        are H for hexadecimal, none or D for decimal, O or Q for octal, 
        and B for binary.  The hex digits a-f are converted to upper case 
        by the assembler.  Note that an Intel-type numeric constant 
        cannot begin with A-F as it would be indistinguishable from a 
        label.  Thus, all of the following evaluate to 255 (decimal):

                   0ffH   255   255D   377O   377Q   11111111B

             A Motorola-type numeric constant starts with a base 
        designator and continues with a string of one or more digits.  
        The base designators are $ for hexadecimal, none for decimal, @ 
        for octal, and % for binary.  As with Intel-type numeric 



                                        5



        constants, a-f are converted to upper case by the assembler.  
        Thus, all of the following evaluate to 255 (decimal):

                          $ff   255   @377   %11111111

             If a numeric constant has a value that is too large to fit 
        into a 16-bit word, it will be truncated on the left to make it 
        fit.  Thus, for example, $123456 is truncated to $3456.


        2.3  String Constants

             A string constant is zero or more characters enclosed in 
        either single quotes (' ') or double quotes (" ").  Single quotes 
        only match single quotes, and double quotes only match double 
        quotes, so if you want to put a single quote in a string, you can 
        do it like this:  "'".  In all contexts except the FCC statement, 
        the first character or two of the string constant are all that 
        are used.  The rest is ignored.  Noting that the ASCII codes for 
        "A" and "B" are $41 and $42, respectively, will explain the 
        following examples:

                  "" and ''           evaluate to $0000
                  "A" and 'A'         evaluate to $0041
                  "AB"                evaluates to $4142

        Note that the null string "" is legal and evaluates to $0000.


        2.4  Expressions

             An expression is made up of labels, numeric constants, and 
        string constants glued together with arithmetic operators, 
        logical operators, and parentheses in the usual way that 
        algebraic expressions are made.  Operators have the following 
        fairly natural order of precedence:

             Highest        anything in parentheses
                            unary +, unary -
                            *, /, MOD, SHL, SHR
                            binary +, binary -
                            LT, LE, EQ, GE, GT, NE
                            NOT
                            AND
                            OR, XOR
             Lowest         HIGH, LOW

             A few notes about the various operators are in order:

             1)   The remainder operator MOD yields the remainder from 
                  dividing its left operand by its right operand.

             2)   The shifting operators SHL and SHR shift their left 
                  operand to the left or right the number of bits 
                  specified by their right operand.



                                        6




             3)   The relational operators LT, LE, EQ, GE, GT, and NE can 
                  also be written as <, <= or =<, =, >= or =>, and <> or 
                  ><, respectively.  They evaluate to $FFFF if the 
                  statement is true, 0 otherwise.

             4)   The logical opeators NOT, AND, OR, and XOR do bitwise 
                  operations on their operand(s).

             5)   HIGH and LOW extract the high or low byte, of an 
                  expression.

             6)   The special symbol * can be used in place of a label or 
                  constant to represent the value of the program counter 
                  before any of the current line has been processed.

             Some examples are in order at this point:

             2 + 3 * 4                          evaluates to 14
             (2 + 3) * 4                        evaluates to 20
             NOT %11110000 XOR %00001010        evaluates to %00000101
             HIGH $1234 SHL 1                   evaluates to $0024
             @001 EQ 0                          evaluates to 0
             @001 = 2 SHR 1                     evaluates to $FFFF

             All arithmetic is unsigned with overflow from the 16-bit 
        word ignored.  Thus:

             32768 * 2                          evaluates to 0


        3.0  Machine Opcodes

             The opcodes of the 6502 and 65C02 processors are listed in 
        the following table along with the various legal argument field 
        formats.  An X in the table indicates that the argument format is 
        legal with the opcode on both processors.  A * in the table 
        indicates that the argument is legal only on the 65C02 processor.  
        Opcodes that are unique to the 65C02 are flagged with a *.

        Opcode                   Argument Format
                  1    2    3    4    5    6    7    8    9    10   11
        ADC       X         *    X         X    X    X    X
        AND       X         *    X         X    X    X    X
        ASL       X                   X    X
        BBR *                                                       X
        BBS *                                                       X
        BCC            X
        BCS            X
        BEQ            X
        BIT       X              *         *
        BMI            X
        BNE            X
        BPL            X
        BRA *          X



                                        7



        Opcode                   Argument Format
                  1    2    3    4    5    6    7    8    9    10   11
        BRK
        BVC            X
        BVS            X
        CLC
        CLD
        CLI
        CLV
        CMP       X         *    X         X    X    X    X
        CPX       X              X
        CPY       X              X
        DEC       X                   *    X
        INC       X                   *    X
        INX
        INY
        JMP       X         X                        *
        JSR       X
        LDA       X         *    X         X    X    X    X
        LDX       X              X              X
        LDY       X              X         X
        LSR       X                   X    X
        NOP
        ORA       X         *    X         X    X    X    X
        PHA
        PHP
        PHX *
        PHY *
        PLA
        PLP
        PLX *
        PLY *
        RMB *                                                  X
        ROL       X                   X    X
        ROR       X                   X    X
        RTI
        RTS
        SBC       X         *    X         X    X    X    X
        SEC
        SED
        SEI
        SMB *                                                  X
        STA       X         *              X    X    X    X
        STX       X                             X
        STY       X                        X
        STZ *     X                        X
        TAX
        TAY
        TRB *     X
        TSB *     X
        TSX
        TXA
        TXS
        TYA




                                        8



             The argument field formats are:

             1)   expression          where expression arbitrary is 
                                      (except RMB and SMB where 
                                      expression is 0 thru 255)

             2)   expression          where the difference between 
                                      expression and the beginning of the 
                                      next instruction must be -128 thru 
                                      127

             3)   (expression)        where expression is arbitrary

             4)   #expression         where expression is -128 thru 255

             5)   A                   Note that the A may be attached to 
                                      the opcode.  Thus "LSR A" and 
                                      "LSRA" are the same.

             6)   expression, X       where expression is arbitrary 
                                      (except STY where expression is 0 
                                      thru 255)

             7)   expression, Y       where expression is 0 thru 255 
                                      (except LDX and STX where 
                                      expression is arbitrary)

             8)   (expression, X)     where expression is 0 thru 255 
                                      (except JMP where expression is 
                                      arbitrary)

             9)   (expression), Y     where expression is 0 thru 255

             10)  bit, expression     where bit is 0 thru 7 and 
                                      expression is 0 thru 255

             11)  bit, expr1, expr2   where bit is 0 thru 7, expr1 is 0 
                                      thru 255, and expr2 follows the 
                                      same rule as 2) above


        4.0  Pseudo Opcodes

             Unlike 6502/65C02 opcodes, pseudo opcodes (pseudo ops) do not 
        represent machine instructions.  They are, rather, directives to 
        the assembler.  These directives require various numbers and 
        types of arguments.  They will be listed individually below.


        4.1  Pseudo-ops -- END

             The END pseudo-op tells the assembler that the source 
        program is over.  Any further lines of the source file are 
        ignored and not passed on to the listing.  If an argument is 
        added to the END statement, the value of the argument will be 



                                        9



        placed in the execution address slot in the Intel hex object 
        file.  The execution address defaults to the program counter 
        value at the point where the END was encountered.  Thus, to 
        specify that the program starts at label START, the END statement 
        would be:

                       END       START

             If end-of-file is encountered on the source file before an 
        END statement is reached, the assembler will add an END statement 
        to the listing and flag it with a * (missing statement) error.


        4.2  Pseudo-ops -- EQU

             The EQU pseudo-op is used to assign a specific value to a 
        label, thus the label on this line is REQUIRED.  Once the value 
        is assigned, it cannot be reassigned by writing the label in 
        column 1, by another EQU statement, or by a SET statement.  Thus, 
        for example, the following statement assigns the value 2 to the 
        label TWO:

             TWO       EQU       1 + 1

             The expression in the argument field must contain no forward 
        references.


        4.3  Pseudo-ops -- FCB

             The FCB (Form Constant Bytes) pseudo-op allows arbitrary 
        bytes to be spliced into the object code.  Its argument is a 
        chain of one or more expressions that evaluate to -128 thru 255 
        separated by commas. The sequence of bytes $FE $FF, $00, $01, $02
	could be spliced into the code with the following statement:

                       FCB       -2, -1, 0, 1, 2


        4.4  Pseudo-ops -- FCC

             The FCC (Form Constant Characters) pseudo-op allows 
        character strings to be spliced into the object code.  Its 
        argument is a chain of zero or more string constants separated by 
        blanks, tabs, or commas.  If a comma occurs with no preceding 
        string constant, an S (syntax) error results.  The string 
        contants are not truncated to two bytes, but are instead copied 
        verbatim into the object code.  Null strings result in no bytes 
        of code.  The message "Kaboom!!" could be spliced into the code 
        with the following statement:

                       FCC       "Kaboom!!"     ;This is 8 bytes of code.




                                       10




        4.5  Pseudo-ops -- FDB

             The FDB (Form Double Bytes) pseudo-op allows 16-bit words to 
        be spliced into the object code.  Its argument is a chain of zero 
        or more expressions separated by commas.  If a comma occurs with 
        no preceding expression, a word of $0000 is spliced into the 
        code.  The word is placed into memory low byte in low address, 
        high byte in high address as per standard MOS Technology order.  
        The sequence of bytes $FE $FF $00 $00 $01 $02 could be spliced 
        into the code with the following statement:

                       FDB       $FFFE, , $0201


        4.6  Pseudo-ops -- IF, ELSE, ENDI

             These three pseudo-ops allow the assembler to choose whether 
        or not to assemble certain blocks of code based on the result of 
        an expression.  Code that is not assembled is passed through to 
        the listing but otherwise ignored by the assembler.  The IF 
        pseudo-op signals the beginning of a conditionally assembled 
        block.  It requires one argument that may contain no forward 
        references.  If the value of the argument is non-zero, the block 
        is assembled.  Otherwise, the block is ignored.  The ENDI pseudo-
        op signals the end of the conditionally assembled block.  For 
        example:

                       IF   EXPRESSION     ;This whole thing generates
                       FCB  $01, $02, $03  ;  no code whatsoever if
                       ENDI                ;  EXPRESSION is zero.

        The ELSE pseudo-op allows the assembly of either one of two 
        blocks, but not both.  The following two sequences are 
        equivalent:

                       IF   EXPRESSION
                       ... some stuff ...
                       ELSE
                       ... some more stuff ...
                       ENDI

             TEMP_LAB  SET  EXPRESSION
                       IF   TEMP_LAB NE 0
                       ... some stuff ...
                       ENDI
                       IF   TEMP_LAB EQ 0
                       ... some more stuff ...
                       ENDI

             The pseudo-ops in this group do NOT permit labels to exist 
        on the same line as the status of the label (ignored or not) 
        would be ambiguous.




                                       11



             All IF statements (even those in ignored conditionally 
        assembled blocks) must have corresponding ENDI statements and all 
        ELSE and ENDI statements must have a corresponding IF statement.

             IF blocks can be nested up to 16 levels deep before the 
        assembler dies of a fatal error.  This should be adequate for any 
        conceivable job, but if you need more, change the constant 
        IFDEPTH in file A65.H and recompile the assembler.


        4.7  Pseudo-ops -- INCL

             The INCL pseudo-op is used to splice the contents of another 
        file into the current file at assembly time.  The name of the 
        file to be INCLuded is specified as a normal string constant, so 
        the following line would splice the contents of file "const.def" 
        into the source code stream:

                       INCL      "const.def"

             INCLuded files may, in turn, INCLude other files until four 
        files are open simultaneously.  This limit should be enough for 
        any conceivable job, but if you need more, change the constant 
        FILES in file A65.H or A65C.H and recompile the assembler.  


        4.8  Pseudo-ops -- ORG

             The ORG pseudo-op is used to set the assembly program 
        counter to a particular value.  The expression that defines this 
        value may contain no forward references.  The default initial 
        value of the assembly program counter is $0000.  The following 
        statement would change the assembly program counter to $F000:

                       ORG       $F000

             If a label is present on the same line as an ORG statement, 
        it is assigned the new value of the assembly program counter.


        4.9  Pseudo-ops -- PAGE

             The PAGE pseudo-op always causes an immediate page ejection 
        in the listing by inserting a form feed ('\f') character before 
        the next line.  If an argument is specified, the argument 
        expression specifies the number of lines per page in the listing.  
        Legal values for the expression are any number except 1 and 2.  A 
        value of 0 turns the listing pagination off.  Thus, the following 
        statement cause a page ejection and would divide the listing into 
        60-line pages:

                       PAGE      60





                                       12



        4.10 Pseudo-ops -- RMB

             The RMB (Reserve Memory Bytes) pseudo-op is used to reserve 
        a block of storage for program variables, or whatever.  This 
        storage is not initialized in any way, so its value at run time 
        will usually be random.  The argument expression (which may
        contain no forward references) is added to the assembly program 
        counter.  The following statement would reserve 10 bytes of 
        storage called "STORAGE":

             STORAGE   RMB       10


        4.11 Pseudo-ops -- SET

             The SET pseudo-op functions like the EQU pseudo-op except 
        that the SET statement can reassign the value of a label that has 
        already been assigned by another SET statement.  Like the EQU 
        statement, the argument expression may contain no forward 
        references.  A label defined by a SET statement cannot be 
        redefined by writing it in column 1 or with an EQU statement.  
        The following series of statements would set the value of label 
        "COUNT" to 1, 2, then 3:

             COUNT     SET       1
             COUNT     SET       2
             COUNT     SET       3


        4.12 Pseudo-ops -- TITL

             The TITL pseudo-op sets the running title for the listing.  
        The argument field is required and must be a string constant, 
        though the null string ("") is legal.  This title is printed 
        after every page ejection in the listing, therefore, if page 
        ejections have not been forced by the PAGE pseudo-op, the title 
        will never be printed.  The following statement would print the 
        title "Random Bug Generator -- Ver 3.14159" at the top of every 
        page of the listing:

                       TITL      "Random Bug Generator -- Ver 3.14159"


        5.0  Assembly Errors

             When a source line contains an illegal construct, the line 
        is flagged in the listing with a single-letter code describing 
        the error.  The meaning of each code is listed below.  In 
        addition, a count of the number of lines with errors is kept and 
        printed on the C "stderr" device (by default, the console) after 
        the END statement is processed.  If more than one error occurs in 
        a given line, only the first is reported.  For example, the 
        illegal label "=$#*'(" would generate the following listing line:

             L  0000   FF 00 00      =$#*'(     CPX       #0



                                       13





        5.1  Error * -- Illegal or Missing Statement

             This error occurs when either:

             1)   the assembler reaches the end of the source file 
                  without seeing an END statement, or

             2)   an END statement is encountered in an INCLude file.

             If you are "sure" that the END statement is present when the 
        assembler thinks that it is missing, it probably is in the 
        ignored section of an IF block.  If the END statement is missing, 
        supply it.  If the END statement is in an INCLude file, delete 
        it.


        5.2  Error ( -- Parenthesis Imbalance

             For every left parenthesis, there must be a right paren-
        thesis.  Count them.


        5.3  Error " -- Missing Quotation Mark

             Strings have to begin and end with either " or '.  Remember 
        that " only matches " while ' only matches '.


        5.4  Error A -- Illegal Addressing Mode

             This error occurs if an addressing mode is specified in the 
        argument field that is not legal with the opcode in the opcode 
        field.  See the table in section 3.0 for the list of legal 
        combinations.


        5.5  Error B -- Branch Target Too Distant

             The 6502 relative branch instructions will only reach -128 
        to +127 bytes from the first byte of the instruction following 
        the branch instruction.  If this error occurs, the source code 
        will have to be rearranged to shorten the distance to the branch 
        target address or a long branch instruction that will reach 
        anywhere (JMP) will have to be used.


        5.6  Error D -- Illegal Digit

             This error occurs if a digit greater than or equal to the 
        base of a numeric constant is found.  For example, a 2 in a 
        binary number would cause a D error.  Especially, watch for 8 or 
        9 in an octal number.




                                       14




        5.7  Error E -- Illegal Expression

             This error occurs because of:

             1)   a missing expression where one is required

             2)   a unary operator used as a binary operator or vice-
                  versa

             3)   a missing binary operator

             4)   a SHL or SHR count that is not 0 thru 15


        5.8  Error I -- IF-ENDI Imbalance

             For every IF there must be a corresponding ENDI.  If this 
        error occurs on an ELSE or ENDI statement, the corresponding IF 
        is missing.  If this error occurs on an END statement, one or 
        more ENDI statements are missing.


        5.9  Error L -- Illegal Label

             This error occurs because of:

             1)   a non-alphabetic in column 1

             2)   a reserved word used as a label

             3)   a missing label on an EQU or SET statement

             4)   a label on an IF, ELSE, or ENDI statement


        5.10 Error M -- Multiply Defined Label

             This error occurs because of:

             1)   a label defined in column 1 or with the EQU statement 
                  being redefined

             2)   a label defined by a SET statement being redefined 
                  either in column 1 or with the EQU statement

             3)   the value of the label changing between assembly passes


        5.11 Error O -- Illegal Opcode

             The opcode field of a source line may contain only a valid 
        machine opcode, a valid pseudo-op, or nothing at all.  Anything 
        else causes this error.




                                       15




        5.12 Error P -- Phasing Error

             This error occurs because of:

             1)   a forward reference in a EQU, ORG, RMB, or SET 
                  statement

             2)   a label disappearing between assembly passes


        5.13 Error R -- Illegal Register

             This error occurs either when the register designator A or B 
        is used with a machine opcode that does not permit it, or when 
        the register designator is missing with a machine opcode that 
        requires it.


        5.14 Error S -- Illegal Syntax

             This error means that an argument field is scrambled.  Sort 
        the mess out and reassemble.


        5.15 Error T -- Too Many Arguments

             This error occurs if there are more items (expressions, 
        register designators, etc.) in the argument field than the opcode 
        or pseudo-op requires.  The assembler ignores the extra items but 
        issues this error in case something is really mangled.


        5.16 Error U -- Undefined Label

             This error occurs if a label is referenced in an expression 
        but not defined anywhere in the source program.  If you are 
        "sure" you have defined the label, note that upper and lower case 
        letters in labels are different.  Defining "LABEL" does not 
        define "Label."


        5.17 Error V -- Illegal Value

             This error occurs because:

             1)   an index offset is not 0 thru 255, or

             2)   an 8-bit immediate value is not -128 thru 255, or

             3)   an FCB argument is not -128 thru 255, or

             4)   an INCL argument refers to a file that does not exist.





                                       16



        6.0  Warning Messages

             Some errors that occur during the parsing of the cross-
        assembler command line are non-fatal.  The cross-assembler flags 
        these with a message on the C "stdout" device (by default, the 
        console) beginning with the word "Warning."  The messages are 
        listed below:


        6.1  Warning -- Illegal Option Ignored

             The only options that the cross-assembler knows are -l and  
        -o.  Any other command line argument beginning with - will draw 
        this error.


        6.2  Warning -- -l Option Ignored -- No File Name
        6.3  Warning -- -o Option Ignored -- No File Name

             The -l and -o options require a file name to tell the 
        assembler where to put the listing file or object file.  If this 
        file name is missing, the option is ignored.


        6.4  Warning -- Extra Source File Ignored

             The cross-assembler will only assemble one file at a time, 
        so source file names after the first are ignored.  To assemble a 
        second file, invoke the assembler again.  Note that under CP/M-
        80, the old trick of reexecuting a core image will NOT work as 
        the initialized data areas are not reinitialized prior to the 
        second run.


        6.5  Warning -- Extra Listing File Ignored
        6.6  Warning -- Extra Object File Ignored

             The cross-assembler will only generate one listing and one 
        object file per assembly run, so -l and -o options after the 
        first are ignored.


        7.0  Fatal Error Messages

             Several errors that occur during the parsing of the cross-
        assembler command line or during the assembly run are fatal.  The 
        cross-assembler flags these with a message on the C "stdout" 
        device (by default, the console) beginning with the words "Fatal 
        Error."  The messages are explained below:


        7.1  Fatal Error -- No Source File Specified

             This one is self-explanatory.  The assembler does not know 
        what to assemble.



                                       17





        7.2  Fatal Error -- Source File Did Not Open

             The assembler could not open the source file.  The most 
        likely cause is that the source file as specified on the command 
        line does not exist.  On larger systems, there could also be 
        priviledge violations.  Rarely, a read error in the disk 
        directory could cause this error.


        7.3  Fatal Error -- Listing File Did Not Open
        7.4  Fatal Error -- Object File Did Not Open

             This error indicates either a defective listing or object 
        file name or a full disk directory.  Correct the file name or 
        make more room on the disk.


        7.5  Fatal Error -- Error Reading Source File

             This error generally indicates a read error in the disk data 
        space.  Use your backup copy of the source file (You do have one, 
        don't you?) to recreate the mangled file and reassemble.


        7.6  Fatal Error -- Disk or Directory Full

             This one is self-explanatory.  Some more space must be found 
        either by deleting files or by using a disk with more room on it.


        7.7  Fatal Error -- File Stack Overflow

             This error occurs if you exceed the INCLude file limit of 
        four files open simultaneously.  This limit can be increased by 
        increasing the constant FILES in file A65.H or A65C.H and 
        recompiling the cross-assembler.


        7.8  Fatal Error -- If Stack Overflow

             This error occurs if you exceed the nesting limit of 16 IF 
        blocks.  This limit can be increased by increasing the constant 
        IFDEPTH in file A65.H or A65C.H and recompiling the cross-
        assembler.


        7.9  Fatal Error -- Too Many Symbols

             Congratulations!  You have run out of memory.  The space for 
        the cross-assembler's symbol table is allocated at run-time using 
        the C library function alloc(), so the cross-assembler will use 
        all available memory.  The only solutions to this problem are to 
        lessen the number of labels in the source program, to use a 



                                       18



        larger memory model (MSDOS/PCDOS systems only), or to add more 
        memory to your machine.























































                                       19

\ No newline at end of file

A a65.html => a65.html +654 -0
@@ 0,0 1,654 @@
<!doctype html>
<html lang="en">
<head>
<style>
body {
    line-height: 140%;
    margin: auto;
    width: 800px;
}

p {
    text-indent: 2em;
}

p.no-indent {
    text-indent: 0em;
}

code {
    font-family: monospace, monospace;
}


pre code {
    background-color: #eee;
    border: 1px solid #999;
    display: block;
    padding: 20px;
}
</style>
<meta charset="utf-8">
<title>A65 Manual</title>
</head>
<body>
<div style="text-align:center">
<h1>A65 6502 Cross-Assembler</h1>
<h3>Version 0.2n</h3>
<h3>Copyright (c) 1986 William C. Colley, III</h3>
<h3>Modifications by Nathan Misner</h3>
</div>
<h3>Legal Note</h3>
<p>This package may be used for any commercial or 
non-commercial purpose.  It may be copied and 
distributed freely provided that any fee charged 
by the distributor of the copy does not exceed the 
sum of:  1) the cost of the media the copy is 
written on,  2) any required costs of shipping the 
copy, and  3) a nominal handling fee.  Any other 
distribution requires the written permission of 
the author.  Also, the author's copyright notices 
shall not be removed from the program source, the 
program object, or the program documentation.</p>

<h3>1.0 - How to Use the Cross-Assembler Package</h3>
<p>First, the question, "What does a cross-assembler do?" needs 
to be addressed as there is considerable confusion on this point.  
A cross-assembler is just like any other assembler except that it 
runs on some CPU other than the one for which it assembles code.  
For example, this package assembles 6502 source code 
into 6502 object code, but it runs on an 8080, a Z-80, 
an 8088, or whatever other CPU you happen to have a C compiler 
for.  The reason that cross-assemblers are useful is that you 
probably already have a CPU with memory, disk drives, a text 
editor, an operating system, and all sorts of hard-to-build or 
expensive facilities on hand.  A cross-assembler allows you to 
use these facilites to develop code for a 6502.</p>

<p>This program requires one input file (your 6502 source 
code) and zero to two output files (the listing and the object).  
The input file MUST be specified, or the assembler will bomb on a 
fatal error.  The listing and object files are optional.  If no 
listing file is specified, no listing is generated, and if no 
object file is specified, no object is generated.  If the object 
file is specified, the object is written to this file in absolute
binary format.</p>

<p>The command line for the 6502 cross-assembler looks like this:</p>
<pre><code>a65 source_file { -l list_file } { -o object_file }</code></pre>
<p class="no-indent">where the { } indicates that the specified item is optional.
Some examples are in order:</p>
<pre><code>a65 test65.asm                          source:   test65.asm
                                        listing:  none
                                        object:   none

a65 test65.asm -l test65.prn            source:   test65.asm
                                        listing:  test65.prn
                                        object:   none

a65 test65.asm -o test65.bin            source:   test65.asm
                                        listing:  none
                                        object:   test65.bin

a65 test65.asm -l test65.prn -o test65.bin
                                        source:   test65.asm
                                        listing:  test65.prn
                                        object:   test65.bin</code></pre>
					
<p>The order in which the source, listing, and object files are 
specified does not matter.  Note that no default file name extensions are supplied by the assembler as this gives rise to portability problems.</p>

<h3>2.0 - Format of Cross-Assembler Source Lines</h3>
<p>The source file that the cross-assembler processes into a 
listing and an object is an ASCII text file that you can prepare 
with whatever editor you have at hand.  The most-significant 
(parity) bit of each character is cleared as the character is 
read from disk by the cross-assembler, so editors that set this 
bit (such as WordStar's document mode) should not bother this 
program.  All printing characters, the ASCII TAB character ($09), 
and newline character(s) are processed by the assembler.  All 
other characters are passed through to the listing file, but are 
otherwise ignored.</p>

<p>The source file is divided into lines by newline character(s).  The internal buffers of the cross-assembler will 
accommodate lines of up to 255 characters which should be more 
than ample for almost any job.  If you must use longer lines, 
change the constant MAXLINE in file a65.h and recompile 
the cross-assembler.  Otherwise, you will overflow the buffers, 
and the program will mysteriously crash.</p>

<p>Each source line is made up of three fields:  the label 
field, the opcode field, and the argument field.  The label field 
is optional, but if it is present, it must begin in column 1. It may
optionally be terminated with a colon character.  
The opcode field is optional, but if it is present, it must not 
begin in column 1.  If both a label and an opcode are present, 
one or more spaces and/or TAB characters must separate the two.  
If the opcode requires arguments, they are placed in the argument 
field which is separated from the opcode field by one or more 
spaces and/or TAB characters.  Finally, an optional comment can 
be added to the end of the line.  This comment must begin with a 
semicolon which signals the assembler to pass the rest of the 
line to the listing and otherwise ignore it.  Thus, the source 
line looks like this:</p>
<pre><code>{label}{ opcode{ arguments}}{;commentary}</code></pre>
<p class="no-indent">where the { } indicates that the specified item is optional.
Some examples are in order:</p>
<pre><code>column 1
   |
   v
   GRONK   LDA   OFFSET, X       ; This line has everything.
           STA   MAILBOX         ; This line has no label.
   BEEP:                         ; This line has no opcode.
   ; This line has no label and no opcode.

   ; The previous line has nothing at all.
           END                   ; This line has no argument.</code></pre>

<h3>2.1 - Labels</h3>
<p>A label is any sequence of alphabetic or numeric characters 
starting with an alphabetic.  The legal alphabetics are:</p>
<pre><code>& , . ? [ \ ] ^ _  ` { | }  ~  A-Z  a-z</code></pre>
<p>The numeric characters are the digits 0-9.  Note that "A" is not 
the same as "a" in a label.  This can explain mysterious U 
(undefined label) errors occurring when a label appears to be 
defined.</p>

<p>A label is permitted on any line except a line where the 
opcode is IF, ELSE, or ENDIF.  The label is assigned the value of 
the assembly program counter before any of the rest of the line 
is processed except when the opcode is EQU, ORG, or SET.</p>

<p>Labels can have the same name as opcodes, but they cannot
have the same name as operators or registers.  The reserved 
(operator and register) names are:</p>
<pre><code>A         AND       EQ        GE        GT        HIGH
LE        LT        LOW       MOD       NE        NOT
OR        SHL       SHR       X         XOR       Y</pre></code>

<p>If a label is used in an expression before it is assigned a 
value, the label is said to be "forward-referenced."  For 
example:</p>
<pre><code>L1   EQU  L2 + 1   ; L2 is forward-referenced here.
L2
L3   EQU  L2 + 1   ; L2 is not forward-referenced here.</code></pre>

<h3>2.2 - Numeric Constants</h3>

<p>Numeric constants can be formed in two ways:  the Intel 
convention or the Motorola convention.  The cross-assembler 
supports both.</p>

<p>An Intel-type numeric constant starts with a numeric 
character (0-9), continues with zero or more digits (0-9, A-F), 
and ends with an optional base designator.  The base designators 
are H for hexadecimal, none or D for decimal, O or Q for octal, 
and B for binary.  The hex digits a-f are converted to upper case 
by the assembler.  Note that an Intel-type numeric constant 
cannot begin with A-F as it would be indistinguishable from a 
label.  Thus, all of the following evaluate to 255 (decimal):</p>
<pre><code>0ffH   255   255D   377O   377Q   11111111B</code></pre>

<p>A Motorola-type numeric constant starts with a base 
designator and continues with a string of one or more digits.  
The base designators are $ for hexadecimal, none for decimal, @ 
for octal, and % for binary.  As with Intel-type numeric constants,
a-f are converted to upper case by the assembler.  
Thus, all of the following evaluate to 255 (decimal):</p>
<pre><code>$ff   255   @377   %11111111</code></pre>

<p>If a numeric constant has a value that is too large to fit 
into a 16-bit word, it will be truncated on the left to make it 
fit.  Thus, for example, $123456 is truncated to $3456.</p>

<h3>2.3 - String Constants</h3>
<p>A string constant is zero or more characters enclosed in 
either single quotes (' ') or double quotes (" ").  Single quotes 
only match single quotes, and double quotes only match double 
quotes, so if you want to put a single quote in a string, you can 
do it like this:  "'".  In all contexts except the DB and DS statements, 
the first character or two of the string constant are all that 
are used.  The rest is ignored.  Noting that the ASCII codes for 
"A" and "B" are $41 and $42, respectively, will explain the 
following examples:</p>
<pre><code>"" and ''           evaluate to $0000
"A" and 'A'         evaluate to $0041
"AB"                evaluates to $4142</code></pre>
<p class="no-indent">Note that the null string "" is legal and evaluates to $0000.</p>

<h3>2.4 - Expressions</h3>
<p>An expression is made up of labels, numeric constants, and 
string constants glued together with arithmetic operators, 
logical operators, and parentheses in the usual way that 
algebraic expressions are made.  Operators have the following 
fairly natural order of precedence:</p>
<pre><code>Highest        anything in parentheses
               unary +, unary -
               *, /, MOD, SHL, SHR
               binary +, binary -
               LT, LE, EQ, GE, GT, NE
               NOT
               AND
               OR, XOR
Lowest         HIGH, LOW</code></pre>
<p class="no-indent">A few notes about the various operators are in order:</p>
<ol>
<li>The remainder operator MOD yields the remainder from dividing its left operand by its right operand.</li>
<li>The shifting operators SHL and SHR shift their left 
operand to the left or right the number of bits 
specified by their right operand.</li>
<li>The relational operators LT, LE, EQ, GE, GT, and NE can 
also be written as <, <= or =<, =, >= or =>, and <> or 
><, respectively.  They evaluate to $FFFF if the 
statement is true, 0 otherwise.</li>
<li>The logical opeators NOT, AND, OR, and XOR do bitwise 
operations on their operand(s).</li>
<li>HIGH and LOW extract the high or low byte, of an 
expression.</li>
<li>The special symbol * can be used in place of a label or 
constant to represent the value of the program counter 
before any of the current line has been processed.</li></ol>
<p class="no-indent">Some examples are in order at this point:</p>
<pre><code>2 + 3 * 4                          evaluates to 14
(2 + 3) * 4                        evaluates to 20
NOT %11110000 XOR %00001010        evaluates to %00000101
HIGH $1234 SHL 1                   evaluates to $0024
@001 EQ 0                          evaluates to 0
@001 = 2 SHR 1                     evaluates to $FFFF</code></pre>
<p class="no-indent">All arithmetic is unsigned with overflow from the 16-bit 
word ignored.  Thus:</p>
<pre><code>32768 * 2                          evaluates to 0</code></pre>

<h3>3.0 - Pseudo Opcodes</h3>
<p>Unlike 6502 opcodes, pseudo opcodes (pseudo ops) do not 
represent machine instructions.  They are, rather, directives to 
the assembler.  These directives require various numbers and 
types of arguments.  They will be listed individually below.</p>

<h3>3.1 - Pseudo-ops -- END</h3>
<p>The END pseudo-op tells the assembler that the source 
program is over.  Any further lines of the source file are 
ignored and not passed on to the listing. If end-of-file 
is encountered on the source file before an 
END statement is reached, the assembler will add an END statement 
to the listing and flag it with a * (missing statement) error.</p>

<h3>3.2 - Pseudo-ops -- EQU</h3>
<p>The EQU pseudo-op is used to assign a specific value to a 
label, thus the label on this line is REQUIRED.  Once the value 
is assigned, it cannot be reassigned by writing the label in 
column 1, by another EQU statement, or by a SET statement.  Thus, 
for example, the following statement assigns the value 2 to the 
label TWO:</p>
<pre><code>TWO       EQU       1 + 1</code></pre>
<p>The expression in the argument field must contain no forward 
references.</p>

<h3>3.3 - Pseudo-ops -- DB</h3>
<p>The DB (Define Bytes) pseudo-op allows arbitrary 
bytes to be spliced into the object code.  Its argument is a 
chain of one or more expressions or string constants 
separated by commas. Any expressions must evaluate to -128 thru 255.
The sequence of bytes $FE, $FF, $00, $01, $02
could be spliced into the code with the following statement:</p>
<pre><code>DB        -2, -1, 0, 1, 2</code></pre>
<p class="no-indent">The NUL-terminated string "nyaa~" could be spliced into the code
with the following statement:</p>
<pre><code>DB        "nyaa~",0      ; This is 6 bytes of code.</code></pre>

<h3>3.4 - Pseudo-ops -- DS</h3>
<p>The DS (Define String) pseudo-op allows 
character strings to be spliced into the object code.  Its 
argument is a chain of zero or more string constants separated by 
blanks, tabs, or commas.  If a comma occurs with no preceding 
string constant, an S (syntax) error results.  The string 
contants are not truncated to two bytes, but are instead copied 
verbatim into the object code.  Null strings result in no bytes 
of code.  The message "Kaboom!!" could be spliced into the code 
with the following statement:</p>
<pre><code>DS        "Kaboom!!"     ;This is 8 bytes of code.</code></pre>

<h3>3.5 - Pseudo-ops -- DW</h3>
<p>The FDB (Form Double Bytes) pseudo-op allows 16-bit words to 
be spliced into the object code.  Its argument is a chain of zero 
or more expressions separated by commas.  The word is placed into 
memory low byte in low address, high byte in high address as per 
standard MOS Technology order.  The sequence of bytes $FE $FF $00
$00 $01 $02 could be spliced into the code with the following statement:</p>
<pre><code>DW        $FFFE, $0000, $0201</code></pre>

<h3>3.6 - Pseudo-ops -- IF, ELSE, ENDI</h3>
<p>These three pseudo-ops allow the assembler to choose whether 
or not to assemble certain blocks of code based on the result of 
an expression.  Code that is not assembled is passed through to 
the listing but otherwise ignored by the assembler.  The IF 
pseudo-op signals the beginning of a conditionally assembled 
block.  It requires one argument that may contain no forward 
references.  If the value of the argument is non-zero, the block 
is assembled.  Otherwise, the block is ignored.  The ENDI pseudo-
op signals the end of the conditionally assembled block.  For 
example:</p>
<pre><code>IF   EXPRESSION     ;This whole thing generates
FCB  $01, $02, $03  ;  no code whatsoever if
ENDI                ;  EXPRESSION is zero.</code></pre>

<p>The ELSE pseudo-op allows the assembly of either one of two 
blocks, but not both.  The following two sequences are 
equivalent:</p>
<pre><code>          IF   EXPRESSION
          ... some stuff ...
          ELSE
          ... some more stuff ...
          ENDI

TEMP_LAB  SET  EXPRESSION
          IF   TEMP_LAB NE 0
          ... some stuff ...
          ENDI
          IF   TEMP_LAB EQ 0
          ... some more stuff ...
          ENDI</code></pre>
<p>The pseudo-ops in this group do NOT permit labels to exist 
on the same line as the status of the label (ignored or not) 
would be ambiguous.</p>
<p>All IF statements (even those in ignored conditionally 
assembled blocks) must have corresponding ENDI statements and all 
ELSE and ENDI statements must have a corresponding IF statement.</p>
<p>IF blocks can be nested up to 16 levels deep before the 
assembler dies of a fatal error.  This should be adequate for any 
conceivable job, but if you need more, change the constant 
IFDEPTH in file a65.h and recompile the assembler.</p>

<h3>3.7 - Pseudo-ops -- INCL</h3>
<p>The INCL pseudo-op is used to splice the contents of another 
file into the current file at assembly time.  The name of the 
file to be INCLuded is specified as a normal string constant, so 
the following line would splice the contents of file "const.def" 
into the source code stream:</p>
<pre><code>INCL      "const.def"</code></pre>

<p>INCLuded files may, in turn, INCLude other files until four 
files are open simultaneously.  This limit should be enough for 
any conceivable job, but if you need more, change the constant 
FILES in file a65.h and recompile the assembler.</p>

<h3>3.8 - Pseudo-ops -- MSG</h3>
<p>The MSG pseudo-op is used to print arbitrary strings and/or
expression results to the console at assembly time. For example,
adding the following line at the end of the program would print
out the amount of free ROM space (assuming the labels are inserted
at the correct spots):
<pre><code>MSG       "Free bytes: ", VectorTable-EndCode</code></pre>

<h3>3.9 - Pseudo-ops -- ORG</h3>
<p>The ORG pseudo-op is used to set the assembly program 
counter to a particular value.  The expression that defines this 
value may contain no forward references.  The default initial 
value of the assembly program counter is $0000.  The following 
statement would change the assembly program counter to $F000:</p>
<pre><code>ORG       $F000</code></pre>
<p>The first ORG statement will specify the starting address of the
binary file (e.g. where it's mapped in memory). Any subsequent ORG
statements will pad the binary file up to the given address. Attempting
to ORG "backwards" (to an address before the program counter) will
cause an error.</p>
<p>If a label is present on the same line as an ORG statement, 
it is assigned the new value of the assembly program counter.</p>

<h3>3.10 - Pseudo-ops -- PAGE</h3>
<p>The PAGE pseudo-op always causes an immediate page ejection 
in the listing by inserting a form feed ('\f') character before 
the next line.  If an argument is specified, the argument 
expression specifies the number of lines per page in the listing.  
Legal values for the expression are any number except 1 and 2.  A 
value of 0 turns the listing pagination off.  Thus, the following 
statement cause a page ejection and would divide the listing into 
60-line pages:</p>
<pre><code>PAGE      60</code></pre>

<h3>3.11 - Pseudo-ops -- RMB</h3>
<p>The RMB (Reserve Memory Bytes) pseudo-op is used to reserve 
a block of storage for program variables, or whatever.  This 
storage is not initialized in any way, so its value at run time 
will usually be random.  The argument expression (which may
contain no forward references) is added to the assembly program 
counter.  The following statement would reserve 10 bytes of 
storage called "STORAGE":</p>
<pre><code>STORAGE   RMB       10</code></pre>

<h3>3.12 - Pseudo-ops -- SET</h3>
<p>The SET pseudo-op functions like the EQU pseudo-op except 
that the SET statement can reassign the value of a label that has 
already been assigned by another SET statement.  Like the EQU 
statement, the argument expression may contain no forward 
references.  A label defined by a SET statement cannot be 
redefined by writing it in column 1 or with an EQU statement.  
The following series of statements would set the value of label 
"COUNT" to 1, 2, then 3:</p>
<pre><code>COUNT     SET       1
COUNT     SET       2
COUNT     SET       3</code></pre>

<h3>3.13 - Pseudo-ops -- TITL</h3>
<p>The TITL pseudo-op sets the running title for the listing.  
The argument field is required and must be a string constant, 
though the null string ("") is legal.  This title is printed 
after every page ejection in the listing, therefore, if page 
ejections have not been forced by the PAGE pseudo-op, the title 
will never be printed.  The following statement would print the 
title "Random Bug Generator -- Ver 3.14159" at the top of every 
page of the listing:</p>
<pre><code>TITL      "Random Bug Generator -- Ver 3.14159"</code></pre>

<h3>4.0 - Assembly Errors</h3>
<p>When a source line contains an illegal construct, the offending filename
and line number are printed to stderr. The line 
is also flagged in the listing with a single-letter code describing 
the error.  The meaning of each code is listed below.  In 
addition, a count of the number of lines with errors is kept and 
printed on the C "stderr" device (by default, the console) after 
the END statement is processed.  If more than one error occurs in 
a given line, only the first is reported.  For example, the 
illegal label "=$#*'(" would generate the following listing line:</p>
<pre><code>L  0000   FF 00 00      =$#*'(     CPX       #0</code></pre>

<h3>4.1 - Error * -- Illegal or Missing Statement</h3>
<p>This error occurs when either:</p>
<ol>
<li>the assembler reaches the end of the source file without seeing an END statement, or</li>
<li>an END statement is encountered in an INCLude file.</li>
</ol>
<p>If you are "sure" that the END statement is present when the 
assembler thinks that it is missing, it probably is in the 
ignored section of an IF block.  If the END statement is missing, 
supply it.  If the END statement is in an INCLude file, delete 
it.</p>

<h3>4.2 - Error ( -- Parenthesis Imbalance</h3>
<p>For every left parenthesis, there must be a right parenthesis.  Count them.</p>

<h3>4.3 - Error " -- Missing Quotation Mark</h3>
<p>Strings have to begin and end with either " or '.  Remember that " only matches " while ' only matches '.</p>

<h3>4.4 - Error A -- Illegal Addressing Mode</h3>
<p>This error occurs if an addressing mode is specified in the 
argument field that is not legal with the opcode in the opcode 
field.</p>

<h3>4.5 - Error B -- Branch Target Too Distant</h3>
<p>The 6502 relative branch instructions will only reach -128 
to +127 bytes from the first byte of the instruction following 
the branch instruction.  If this error occurs, the source code 
will have to be rearranged to shorten the distance to the branch 
target address or a long branch instruction that will reach 
anywhere (JMP) will have to be used.</p>

<h3>4.6 - Error D -- Illegal Digit</h3>
<p>This error occurs if a digit greater than or equal to the 
base of a numeric constant is found.  For example, a 2 in a 
binary number would cause a D error.  Especially, watch for 8 or 
9 in an octal number.</p>

<h3>4.7 - Error E -- Illegal Expression</h3>
<p>This error occurs because of:</p>
<ol>
<li>a missing expression where one is required</li>
<li>a unary operator used as a binary operator or vice-versa</li>
<li>a missing binary operator</li>
<li>a SHL or SHR count that is not 0 thru 15</li>
</ol>

<h3>4.8 - Error I -- IF-ENDI Imbalance</h3>
<p>For every IF there must be a corresponding ENDI.  If this 
error occurs on an ELSE or ENDI statement, the corresponding IF 
is missing.  If this error occurs on an END statement, one or 
more ENDI statements are missing.</p>

<h3>4.9 - Error L -- Illegal Label</h3>
<p>This error occurs because of:</p>
<ol>
<li>a non-alphabetic in column 1</li>
<li>a reserved word used as a label</li>
<li>a missing label on an EQU or SET statement</li>
<li>a label on an IF, ELSE, or ENDI statement</li>
</ol>

<h3>4.10 - Error M -- Multiply Defined Label</h3>
<p>This error occurs because of:</p>
<ol>
<li>a label defined in column 1 or with the EQU statement being redefined</li>
<li>a label defined by a SET statement being redefined either in column 1 or with the EQU statement</li>
<li>the value of the label changing between assembly passes</li>
</ol>

<h3>4.11 - Error O -- Illegal Opcode</h3>
<p>The opcode field of a source line may contain only a valid 
machine opcode, a valid pseudo-op, or nothing at all.  Anything 
else causes this error.</p>

<h3>4.12 - Error P -- Phasing Error</h3>
<p>This error occurs because of:</p>
<ol>
<li>a forward reference in a EQU, ORG, RMB, or SET statement</li>
<li>a label disappearing between assembly passes</li>
</ol>

<h3>4.13 - Error R -- Illegal Register</h3>
<p>This error occurs either when the register designator A or B 
is used with a machine opcode that does not permit it, or when 
the register designator is missing with a machine opcode that 
requires it.</p>

<h3>4.14 - Error S -- Illegal Syntax</h3>
<p>This error means that an argument field is scrambled.  Sort the mess out and reassemble.</p>

<h3>4.15 - Error T -- Too Many Arguments</h3>
<p>This error occurs if there are more items (expressions, 
register designators, etc.) in the argument field than the opcode 
or pseudo-op requires.  The assembler ignores the extra items but 
issues this error in case something is really mangled.</p>

<h3>4.16 - Error U -- Undefined Label</h3>
<p>This error occurs if a label is referenced in an expression 
but not defined anywhere in the source program.  If you are 
"sure" you have defined the label, note that upper and lower case 
letters in labels are different.  Defining "LABEL" does not 
define "Label."</p>

<h3>4.17 - Error V -- Illegal Value</h3>
<p>This error occurs because:</p>
<ol>
<li>an index offset is not 0 thru 255</li>
<li>an 8-bit immediate value is not -128 thru 255</li>
<li>a DB argument is not -128 thru 255</li>
<li>an ORG statement is attempting to seek backwards in the file</li>
<li>an INCL argument refers to a file that does not exist</li>
</ol>

<h3>5.0 - Warning Messages</h3>
<p>Some errors that occur during the parsing of the cross-
assembler command line are non-fatal.  The cross-assembler flags 
these with a message on the C "stdout" device (by default, the 
console) beginning with the word "Warning."  The messages are 
listed below:</p>

<h3>5.1 - Warning -- Illegal Option Ignored</h3>
<p>The only options that the cross-assembler knows are -l and  
-o.  Any other command line argument beginning with - will draw 
this error.</p>

<h3>5.2 - Warning -- -l Option Ignored -- No File Name</h3>
<h3>5.3 - Warning -- -o Option Ignored -- No File Name</h3>
<p>The -l and -o options require a file name to tell the 
assembler where to put the listing file or object file.  If this 
file name is missing, the option is ignored.</p>

<h3>5.4 - Warning -- Extra Source File Ignored</h3>
<p>The cross-assembler will only assemble one file at a time, 
so source file names after the first are ignored.  To assemble a 
second file, invoke the assembler again.  Note that under CP/M-80,
the old trick of reexecuting a core image will NOT work as 
the initialized data areas are not reinitialized prior to the 
second run.</p>

<h3>5.5  Warning -- Extra Listing File Ignored</h3>
<h3>5.6  Warning -- Extra Object File Ignored</h3>
<p>The cross-assembler will only generate one listing and one 
object file per assembly run, so -l and -o options after the 
first are ignored.</p>

<h3>6.0 - Fatal Error Messages</h3>
<p>Several errors that occur during the parsing of the cross-
assembler command line or during the assembly run are fatal.  The 
cross-assembler flags these with a message on the C "stdout" 
device (by default, the console) beginning with the words "Fatal 
Error."  The messages are explained below:</p>

<h3>6.1 - Fatal Error -- No Source File Specified</h3>
<p>This one is self-explanatory.  The assembler does not know what to assemble.</p>

<h3>6.2 - Fatal Error -- Source File Did Not Open</h3>
<p>The assembler could not open the source file.  The most 
likely cause is that the source file as specified on the command 
line does not exist.  On larger systems, there could also be 
privilege violations.  Rarely, a read error in the disk 
directory could cause this error.</p>

<h3>6.3 - Fatal Error -- Listing File Did Not Open</h3>
<h3>6.4 - Fatal Error -- Object File Did Not Open</h3>
<p>This error indicates either a defective listing or object 
file name or a full disk directory.  Correct the file name or 
make more room on the disk.</p>

<h3>6.5 - Fatal Error -- Error Reading Source File</h3>
<p>This error generally indicates a read error in the disk data 
space.  Use your backup copy of the source file (You do have one, 
don't you?) to recreate the mangled file and reassemble.</p>

<h3>6.6 - Fatal Error -- Disk or Directory Full</h3>
<p>This one is self-explanatory.  Some more space must be found 
either by deleting files or by using a disk with more room on it.</p>

<h3>6.7 - Fatal Error -- File Stack Overflow</h3>
<p>This error occurs if you exceed the INCLude file limit of 
four files open simultaneously.  This limit can be increased by 
increasing the constant FILES in file A65.H or A65C.H and 
recompiling the cross-assembler.</p>

<h3>6.8 - Fatal Error -- If Stack Overflow</h3>
<p>This error occurs if you exceed the nesting limit of 16 IF 
blocks.  This limit can be increased by increasing the constant 
IFDEPTH in file A65.H or A65C.H and recompiling the cross-
assembler.</p>

<h3>6.9 - Fatal Error -- Too Many Symbols</h3>
<p>Congratulations!  You have run out of memory.  The space for 
the cross-assembler's symbol table is allocated at run-time using 
the C library function alloc(), so the cross-assembler will use 
all available memory.  The only solutions to this problem are to 
lessen the number of labels in the source program, to use a 
larger memory model (MSDOS/PCDOS systems only), or to add more 
memory to your machine.</p>

</body>
</html>
\ No newline at end of file

M a65util.c => a65util.c +2 -2
@@ 389,7 389,7 @@ void bseek(unsigned a) {
		}
		/* don't allow seeking backwards */
		else if (cursor > a) {
			error('S');
			error('V');
		}
		/* pad the file to make up the difference */
		else {


@@ 452,7 452,7 @@ void error(char code) {
			default:	description = ERR_UNKNOWN;		break;
			}

			printf("%s:%d: %c -- %s\n", filestk[filesp].filename, filestk[filesp].linenum, code, description);
			fprintf(stderr, "%s:%d: %c -- %s\n", filestk[filesp].filename, filestk[filesp].linenum, code, description);
		}
	}
    return;

M readme.txt => readme.txt +1 -2
@@ 14,8 14,7 @@ your workflow.
  "dialects" like all the popular assemblers do
- It's an absolute assembler, so no linking
- No macro support
- I'm like 90% sure that it won't like Unicode characters (but who knows, it
  might...)
- It clears the upper bit when reading input files, so no UTF-8 support

=====Why to use this assembler=====
- The code is well laid out and easy to understand and modify in case you want