From Atari Wiki
Jump to navigation Jump to search
                     Copyright (C) 1990 by Natrlich!
                        This file is copyrighted!
                  Refer to the documentation for details.

   NASM65 --- an Atari 8-Bit Crossassembler for the Atari ST (et al.)

                         Manual v1.9* for NASM65
                         Currently not quite up to date

         Copyright ½ 1992 by Natrlich!
            on sources, binaries and manuals

                  ¯¯ Bang that Bit that doesn't Bang ®®

   I n t r o d u c t i o n

   NASM65 is a <portable> single-pass cross-assembler that produces 6502
   code. NASM65 currently runs on 680x0 Ataris under TOS, on the AMIGA 
   and apparently under UNIX. It its conceivably portable to MSDOS.
   The assembler produces two kinds of output, directly executable code 
   for the Atari 8-Bit computer (FF FF headers and all that...) or 
   linkable modules to be used with NLINK65. Instantly executable code 
   (furtheron referred to as "runnable") is non-relocatable and 
   non-linkable. The other kind of output are relocatable and linkable 
   object files. That production mode is further on referred to as 
   "relocatable". NASM65 is closely compatible to MAC65 from OSS 
   (now ICD), but not 100%. The differences will be noted later on. 
   Compatibility worsens somewhat when relocatable output is produced. 
   (Apple and C64 users, have a peek at XTRCTBIN)

   U s a g e

   nasm65 [-{rwbqx}][-{tn}][-e number][-o binary][-h includedir] <source>

   -t    TOS switch, wait for a keypress after running

   -w    The "what the ...." switch, even though errors occured an output
         file is generated.

   -r    The runnable switch. NASM65 will create an Atari 8-Bit binary
         file for direct execution

   -h    Supply alternate header directory (Default is taken from the
         Environment variable >INCLUDE<)

   -e    Limit the number of errors: 0 = show all

   -o    Specify alternate output file pathname (or filename)

   -b    Don't emulate MAC/65 too closely (will improve output in the
         runnable mode)

   -x    List all global variables. Defined globals appear with a '*'
         in front.
   -q    Quiet flag, probably turns up the volume
   -n    Noisy tokenization. Try it on your ST.
   There is no order in which switches or the source file have to appear.

   C r e a t i n g   r u n n a b l e   A T A R I   8 - B i t   f i l e s

   Type from a shell:
   nasm65 -r <source.s65>

   That will create a output file {source}.COM
   Transfer this file (with NASTY for instance) to a 8-Bit Atari computer
   and execute it there.

   C r e a t i n g   l i n k a b l e   m o d u l e s

   Type from a shell
   nasm65 <source.s65>
   That will create a output file {source}.o65, that can then be linked
   together with other relocatable output files.

   H o w   N A S M 6 5   f i n d s   i t s   f i l e s

   Source files:

   NASM65 first looks in the current directory for the file you specified
   on the command line. After that it tries again by replacing the filename
   extension with .S65. If that doesn't work either, NASM65 signals an
   error. This means if you type "nasm65 foo" and you have a file FOO and a
   file FOO.S65, the file "FOO" will be loaded.

   Include files:

   If the extension has been omitted and it looks like a filename,
   not a pathname, NASM65 will append the default extension .H65 and
   insert the default header path at the front.
   Else NASM65 looks first in the current directory for the include file.
   Afterwards NASM65 replaces the extension with .H65 and it will look
   in the directory given either by the environment variable INCLUDE or 
   by the command option '-h'.
   If NASM65 fails again, it will try last to open the file without the
   .H65 extension.

   S o u r c e   c o d e   f o r   N A S M 6 5

   Generally speaking MAC65 style code  w i l l  work with NASM65. Other
   assemblers' source (like SYNASM or MAE) might need to be converted to
   NASM65 syntax before assembly [a SED script might be helpful...].
   Problems may appear because of the single-pass structure of the
   assembler. Conventional assemblers use two passes, one pass collects
   all the symbols and if possible assigns values to them. The second pass
   actually produces the code. NASM65 tries to do it all in one pass.
   Of course there is the problem with forward references f.e.:
            bne   bar
        bar clc

   When the assembler encounters "bne bar" it doesn't yet know, what
   value "bar" has and so can't produce proper code for that branch
   yet. Only when the bar label is encountered is generation possible.
   Therefore NASM65 has some limitations on the code that it can produce.
   You will find out about it...

   A   f e w   g o l d e n   r u l e s

         [Take those marked with a ! really seriously]

    1! Don't produce code for zeropage ($00-$FF), be careful of
       wraparounds $FFFF-$00 if you assemble ROM-code.

    2! Define macros and equates EARLY! the sooner the better.

    3. The fewer forward references you use, the less trouble you and
       NASM65 will have. Forward references are neccessary only for
       ¯Branches®, ¯Subroutines® and ¯Data®. Coding like this
                lda   #$40
                sta   nmien
          nmien =     $D40E
       is not only in bad style, it's screamingly inefficient and doesn't
       work with NASM65 in the module mode.

    4! In the "relocatable" mode, all label settings that are not PC-
       relative (f.e. `FOO=$D4'  but not  `FOO:   LDA #2') must be
       done before the label is used.
       <label> = <value>

    5! Never put macro definitions after their first invocation.

    6. Try to define everything (labels and macros) ahead of its first 

    7. Put macros and equates, especially if they are used in several
       different sources, in common include files. Never mind that
       file foo.s65 needs only one of the 100 macro definitions of
       "macro.h65" and 10 of the 500 equates of "defines.h65", NASM65 will
       be grateful! Be sure to keep PC-relative labels out of the
       include files as MUCH AS POSSIBLE. It makes for better style and
       also keeps the error count down, when linking your objects.

    8. Always remember that MAC65 is a three/two-pass NASM65 is a 
       single-pass assembler.

    9. Always define everything ahead of its usage, except PC-relative
       labels like branch, subroutine and data labels.

   10. Use local labels as much as possible. Use global labels only for
       system equates and subroutines and data that are accessed by out-
       side files.

   11! If you are into conditional assembly and you like to control that
       with a central include file, be sure to use non-PC relative labels
       as switches.

          .if .def errorchecking

       will **FAIL**, when two files using the same include file are lin-
       ked together. Rather use

       errorchecking = 1

          .if .def errorchecking
       or even better
          .if errorchecking

   12! Undefine forward referenced labels in .MACRO definitions. It pays!
   13. Apple and C64 users oughta ensure that addresses in their object
       files are ascending from start to end. No code like this will
       work for you:
            bcc foo
         foo rts

   T h e   " r e l o c a t a b l e "   m o d e

   The relocatable mode is the default mode, you did not supply a -r
   switch on the command line. That means NASM65 will produce an object
   file suitably for linking and relocation at runtime. The relocatable
   mode imposes some restrictions on your source code.

   Forward references can only be made to PC-relative addresses, that
   means that all System-equates like (STACK=$100) have to be done before
   they are used the first time. This is not really a problem since it is
   good style to use a central include file for global symbols that
   is read in at the beginning of the source. Since the linker can also
   only link PC-relative global symbols (local symbols and not PC-relative
   labels are not saved in the object file) NASM65 makes it a necessity.
   There is one exception to this rule, see 'Linking Zeropage-labels'.

   File "sys.h65" :

   NMIEN = $D40E
   STACK = $100

   File "s1.s65":

      .include #sys.h65

      lda   #$C0
      sta   NMIEN    ;; from sys.h65
      jsr   bar      ;; not in s1.65 or sys.s65 !! -> open reference
      bcc   foo

   File "s2.s65":

      .include #sys.h65

   bar:              ;; here it gets defined. NLINK s1 s2 would
      lda   STACK    ;; produce a file with bar in s1 correctly
      clc            ;; set to the address of bar in s2
      adc   STACK+1

   The second goal that was set for NASM65 (apart from being a MAC65
   compatible cross-assembler) was relocatability and linkability. And
   as far as *I* know, no assembler exists that does produce run-time 
   relocatable 6502 code. The greatest problem with relocating 6502 code 
   is with source code like this:

            lda   #>foo    ; get 16-Bit address into A an X
            ldy   #bar-foo ; get length in Y
            ldx   #<foo
            jsr   print    ; JSR to some routine
            bcc   out

   foo:    .byte "F.T.O.E. coming soon.." ; the message to be printed

   Now for you the human, it's quite easy to figure out that the
   "lda" and "ldx" belong together, but for the relocating code it's not
   so easy. Semantic checking of this kind easily slides into the black
   magic dept. of computer science (--> A.I.) and that would be just
   Ok so there are some limitations in what you can do, here are a
   couple of things to know about NASM65.

   0. Linkable labels are:
         ZEROpage labels declared with ==
         All PC-relative global labels
         All PC-relative macro labels, except those starting with @
   1. Arithmetic with relative addresses is a tricky thing, since
      you don't know at assembly time, what the value is. Therefore
      many operations don't make sense any more. There are only a few
      operations you _can_ use with PC-relative labels. This does not
      apply to the runnable mode by the way.
      Coming up the only valid operations possible in the relocatable
      mode. Refer to the appendix for <words>...

         <value> <operation> <value> -> <value>
         <operation> <value>         -> <value>

         <address> '+'  <value>      -> <address>
         <address> '-'  <value>      -> <address>
         <value>   '+'  <address>    -> <address>
         <address> '-'  <address>    -> <value>

         '<' <address>               -> <saddress> (* careful!! *)
         '>' <address>               -> <saddress> (* careful!! *)

      For example:

         bput  1,:header,:l_header,X_IS_READY
:header  .byte    "Starting off with this little test...",155
:l_header   = *-:header

      That ain't working...
      This will give a warning (not an error, although that might
      be changed in the future), because :l_header was assumed to
      be an address, but is in fact a value.

         bput  1,:header,:e_header-:header,X_IS_READY
:header  .byte    "Starting off with this little test...",155

      THAT's the way you do it.

   2. An immediate expression that takes either the LSB or the MSB of an 
      PC-relative address like this
            lda   #>bar    ; grab MSB of `bar'
            lda   #<bar    ; grab LSB of `bar'

      must start off with a '>' (that is  "#>foo" or "#>[foo+1]")
      or with a '<'. Although in MAC65 "lda #LABEL" and "lda #<LABEL" is 
      the same, it isn't for NASM65. Actually the same code will be 
      assembled, but relocatability and linkability will be impaired.
      Note that there has been a change in operator precedence from MAC65
      concerning the unary '>' and '<' operators. Refer to the table in
      the appendix. MAC65 treated "lda #>foo-2" as "lda #[>foo]-2, but
      NASM65 treats it as lda #>[foo-2]. This might make recoding of some
      old code necessary.

   3. .DS works very much different in the relocatable mode than in the
      runnable mode (see also "Other Useful Stuff To Know"). Since you 
      can't use *= anyway, this is not the way to define zeropage labels 
      or any other non-PC relative labels for that matter. Like

          *=$F0            ;;; WRONG
      SRC .ds 2            
   4.  .= works different from the way it does in the runnable mode. MAC/65
       allows pass conditional assembly like this:
         pass .= pass + 1
            .if pass=1
               .include ...

       Since NASM65 is single-pass, this isn't a useful technique anymore.
       Normally NASM65 would think that 'pass' on the right side of .= is
       a forward reference. But in the runnable, for enhanced com-
       patibility with MAC/65, pass will get the value of the program 
       In the relocatable mode, 'pass' on the right side of .= WILL be
       treated as a forward reference, resulting in numerous errors.

   L i n k i n g    Z e r o p a g e - l a b e l s

   There is a way to link zeropage labels with NASM65, so that for
   example common vectors can be shared. As you have come to like
   it, here is an example to make the point:

         foo == $88           ; declare this 0-page label as linkable

         lda   #>BAR          ; just some stuff to fill up space
         sta   FOO+1          ; simple expressions are OK
         lda   #<BAR
         sta   FOO
         jmp   FUBAR

   bar:  .byte    $74

         .zext foo            ; tell that foo is an external 1 byte address
                              ; that shouldn't be relocated
         ldy   #0             ; Let's use FOO
         lda   (FOO),y
         sta   $2C8

   NASM65 won't mind some simple arithemtic, as long as you don't use
   PC relative addresses. Note that $45 + $120 = $65 and not $165. Don't
   try to be overly clever with this feature, keep it simple and stupid
   and be happy that this works at all.

   What you must not do by the way is this:
         .ZEXT FOO            ; that's ok
   FOOLSB = FOO               ; but this and
   FOOMSB = FOO + 1           ; that won't work

   .ZEXT is more or a less a hack and conflicts with the generality of
   the rest of NASM65. Sorry. But doing this right would require
   a whole new internal assembler structure. 

   D i f f e r e n c e s   b e t w e e n   M A C 6 5   a n d   N A S M 6 5

   Text after a correctly parsed instruction is assumed to be part of the
   comment field by MAC65. NASM65 treats this as garbage. Every comment
   has to start with a semicolon ';'.
      lda  #2loser comment w/NASM65
   is treated by MAC65 as
      lda  #2    loser comment w/NASM65
   but generates an error with NASM65.

   obsolete directives
   are parsed but nothing will happen.

   '>' and '<' (unary) have lower precedence.

   MAC65 generates a new binary header at least every 252 bytes (don't
   ask me why). You can check with CHKFFFF that actually the same amount
   of code (in the runnable mode of course) was generated by NASM65 but
   with much less headers. That makes by the way loading of binary files
   much faster and decreases overall size.

   The include syntax is similiar, but adjusts to your kind of OS. So
   you can't expect to assemble instructions like
   properly on the ST for instance.

   NASM65 currently produces no listing file!

   .REF may now be used anywhere in an expression, whereas MAC65
   allowed .REF only in .IF expressions.

   .SET doesn't work anymore. Compiling with an offset must be (clumsily ?) 
   simulated by using the linker.

   Due to the single-pass nature of NASM65, NASM65 does not do a third
   pass over macros like MAC65 does. For example:
                     .macro   bar
                        jmp  foo
    MAC/65 produces:          NASM65 produces:
      $2000 jmp   $2003          jmp   $2003
      $2003 jmp   $2006          jmp   $2003
      $2006 jmp   $2009          jmp   $2006

   To alleviate this problem rewrite the macro as:
                     .macro   bar
                        .if .def foo
                           .undef foo
                        jmp   foo


   O t h e r   u s e f u l   s t u f f   t o   k n o w

   When assembling in the runnable mode, NASM defines a label "__RUN"
   for you. This way you can with the use of a simple .IF statement
   have a file that can be both, assembled as a standalone program and
   as a linkable module.
         .if .def __RUN

   You have one new directive at your disposal. It's called .ALIGN and 
   aligns the module on a given boundary (like a page f.i.).

   Also NASM always defines the label __NASM65, for conditional assembly
   depending on the assembler used for example.

   U s i n g   r u n t i m e   r e l o c a t i o n

   The bad news is that the mover isn't quite as smart as the linker
   and can't properly move all the code there is. To keep the MOVER happy
   you should obey these golden rules:

   |R_START means beginning of your code. This is the first assembled
                  byte of the first object file linked.
   |R_END   means end of your code. This is the last assembled byte of
                  the last object file or library. (Excluding the mover)

   1. The MOVER fixes all addresses that point into the program space
      starting from |R_START - 1  to |R_END, If you somehow managed to
      convince NASM65 to assemble |R_START-$100, you will surely lose.
      Also bad is coding like this:
         jmp   *+40
         .byte "Fooble"
      This probably won't work anyway, but the MOVERs sure won't relocate
      it as well.   

   2. The MOVER needs some information about the program it has to move.
      This is done with the aid of two tables. I won't discuss the makeup
      of these tables, as it would be too much type work. But you can
      keep the size of these tables down, by keeping data and code as
      seperate as possible. But this is something you should only consider,
      if your program needs 32K file space.

   3. Don't expect to get 65C02 insructions relocated correctly. 65C02
      compatibility was a last ditch effort on my part. Since the Atari 
      8-Bit doesn't have a 65C02 this isn't really a problem. Try it out 
      though, maybe it will even work.

   E r r o r s

   Yes it can happen to the best of us. Errors in the source code. NASM65
   will try to tell you as clearly as possibly in 1000 words or less, where
   and why you lost. The form of the message is in most cases, something
   like this:

   "source filename"[ linenumber in source], <continued>
      macroname[ linenumber in macro], ...  "Error [error message]"

   There are several different error levels
      a) normal errors         -- f.e. syntax, undefined macro...
      b) fatal errors          -- f.i. out of memory. file not found...
      c) internal errors       -- this shouldn't happen
      d) serious ....up errors -- NASM65 crashed downright. VERY VERY BAD!

   You can fix errors of type 'a' and 'b', they are your problem. Errors
   of type 'c' and 'd' are NASM65's problem, there is probably nothing you
   can do.


   W a r n i n g s

   Warnings aren't errors 'cause there is a good chance that the assembler
   will actually do what you want to happen. BUT if things go wrong it
   isn't a bad idea to look at the warnings.

   A p p e n d i x

   M e m o r y   r e q u i r e m e n t s

   NASM65 is memory hungry. Although it does use dynamic memory allocation
   instead of fixed tables it needs after its load about 150K space to
   work in. For larger files figure about 1/4 MB. There is a real, true,
   honest-to-goodness garbage collector coming up in version 3.0 (sorry).
   (Well just maybe *NOT*)

   S o u r c e   C o d e

   The lines of source must adhere to some positional restrictions as
   you may easily figure out from the schemata below. Just in case you
   never saw an assembler before.

   Beforehand introducing a few shortcuts
      [..] = optional something '..' enclosed in square brackets
      ^    = Start of line
      $    = End of line
      .    = any number of SPACE or TAB but at least one
      _    = any number of SPACE or TAB possibly none
      X    = any characters except LF possibly none
      other characters represent themselves


   foo   inx
         lda   foo
   foo   lda   foo
         lda   #2
   foo   lda   #2     ; this is a comment
         .byte 2
   foo   .byte 2
         .byte 2,"FOO"
   foo   .byte 2,"FOO"
   foo   POKE  foo,3
   foo   = 34

   S p e c i a l s

      * denotes the program counter or PC, and can be used in expressions
      like any other label.

      Used by ROL ROR LSL LSR to indicate usage of the 6502 A-register.
      Therefore you can't use A as a label.
      Used by indexed or indirect instruction such as LDA (FOO,X) or
      STA BAR,Y. Don't use X or Y as labels as well.

   I d e n t i f i e r

   An identifier is either a label or a macroname. The morphological
   structure of an identifier is simply any string of characters that
   is taken from this character set [A-Z a-z 0-9 $ @ _ . : ?].
   An identifier may not begin with a number. Non macro identifiers should 
   not begin with a '@' and user identifiers should generally not start
   with a '_' (underscore), but this isn't enforced. An identifier must 
   not just be "A" or "a", "X" or "x", "Y" or "y". Internally all 
   identifiers are converted to uppercase, so that there is no difference 
   between "small" and "SMALL". A label that begins with a ':' or '?' is 
   always a local label.
   Label definitions may optionally be directly followed by a ':', which
   isn't part of the label. An <equate> is a label that gets its value
   by a '=' assignment.

   A = 45      ;; wrong!, you can't use A as a label name
   FOO = 23    ;; OK!
   FOO:  inx   ;; OK global label = "FOO"
   Foo:: inx   ;; OK global label = "FOO:"
   :FoO: inx   ;; OK local label  = ":FOO"
   FoO:: inx   ;; WRONG! This is the same label as the one two lines up
   ?_:_:   DEX ;; OK local label  = "?_:_"
   01234       ;; WRONG! label would start off with a digit
   ?01234      ;; OK local label  = "?01234"
   :01234      ;; OK local label  = ":01234"
   ?01234      ;; WRONG! label is already defined (two lines up)
      .macro FOO  ;; OK. Macros may have the same name as labels!

   A s s i g n m e n t s

   There are four different possibilities to assign a value to a label.
   Note that '^' denotes the beginning of a source line (as above). Also
   be aware that some of these <labels> are <equates>. The distinction
   is important when you look at macros.

   Type A:
   ^<label> =  <expr>
      This assigns the value of <expr> to <label>. You can't overload
      this label with another assignment.
      foo = 2     ;; lda #foo would assemble to A9 02
      bar = *+foo ;; bar = PC + 2. PC-relative!
      NMIEN=$D40E ;; sta NMIEN would assemble to 8D 0E D4
      foo = 3     ;; doesn't work, cause foo is already defined!

   Type B
   ^<label> .= <expr>
      This is almost the same as <label> = <expr> with the difference
      that you can overload <label> again! Using .= with forward references
      is possibly dangerous.
      foo .= 2     ;; lda #foo would assemble to A9 02     <-+
      bar .= *+foo ;; bar = PC + 2. PC-relative!             |
      NMIEN.=$D40E ;; sta NMIEN would assemble to 8D 0E D4   |
      foo .= 3     ;; Works fine, cause its a .= assignment -+
   Type C
   ^<label> == <expr>
      This is used in conjunction with .ZEXT. Tells the assembler to
      include this zeropage! label in the list of linkable symbols.
      foo == $56   ;; OK!
      foo == $456  ;; WRONG! only zeropage allowed

   Type D
      A label that isn't followed by '==', '=' or '.=' takes on the
      value of *, the program counter.
      foo  jmp foo ;; endless loop!

   O p e r a t o r s

   [<expr>]             Parenthesis (actually brackets)
   <expr> + <expr>      Addition
   <expr> - <expr>      Subtraction
   - <expr>             Minus
   <expr> * <expr>      Multiplication
   <expr> / <expr>      Division
   <expr> \ <expr>      Modulo
      These are the normal operators for unsigned 16-Bit values, that you
      know from C. And they behave that way too, 'cause NASM65 is written
      in C. Note that 16-Bits overflow after 65535 to 0.
      Some examples of results to expect
      5/3=1    5/2=2       5/1=5    5/2*2=4  4+1-6=65535
      4-2+2=4  4-[2+2]=0   4-2*2=0  5\3=1    8\2=0
      -1=65535 8+[-1]=7

   <expr> .NOT <expr>   Boolean negation
   <expr> .AND <expr>   Boolean AND
   <expr> .OR  <expr>   Boolean OR
   <expr>  =   <expr>   Equality
   <expr>  <>  <expr>   Inequality
   <expr>  <   <expr>   Less than
   <expr>  >   <expr>   More than
   <expr>  >=  <expr>   More or equal
   <expr>  <=  <expr>   Less or equal
      These too are quite like C. Everything which isn't 0 is taken to
      be 'true'. 0 therefore means 'false'.
      .NOT 0   = 1   0 .AND -2 = 0   1 .AND 1 = 1
      5 .OR 0  = 1   0 .OR  0  = 0   .NOT 1 .OR .NOT 0 .AND .1 = 0
      43 > 43  = 0   43 > -1   = 0   43 > 0   = 1
      43 < 43  = 1   43 < -1   = 1   43 < 0   = 0
      43 >= 43 = 1   43 >= -1  = 0   43 >= 0  = 1
      43 <= 43 = 1   43 <= -1  = 1   43 <= 0  = 0
      43 =  43 = 1   43  = -1  = 0   43 =  0  = 0
      43 <> 43 = 0   43 <> -1  = 1   43 <> 0  = 1

   <expr> & <expr>      Bitwise AND
   <expr> ! <expr>      Bitwise OR
   <expr> ^ <expr>      Bitwise EOR
      These are your regular bitwise operators, what is there to say ?
      Some examples just for fun:
      $0001 & $FFFE = $0000   $5AF0 & $5555 = $5050
      $0001 ! $FFFE = $FFFF   $5AF0 ! $5555 = $5FF5
      $0001 ^ $FFFE = $FFFF   $5AF0 ^ $5555 = $0FA5

   .DEF <label>         Label defined ?
   .REF <label>         Label referenced ?
      .DEF and .REF can be used to determine, whether a label has already
      been defined or whether it has been referenced already. There is
      unlike MAC65 no restriction on usage.
         .if .not .def foobar
            .error "Should have included fooble.foobar first!"
         lda   #.ref leopold * 6  ;; senseless, but it works!

   O p e r a t o r   p r e c e d e n c e

   Associativity   Precedence level  Operator  Description

         -              9              .DEF     Special
         -              9              .REF     Special

         L              8               -       Unary minus
         L              8              .NOT     Boolean NOT

         L              7               *       Multiplication
         L              7               /       Division
         L              7               \       Modulo

         L              6               +       Addition
         L              6               -       Subtraction

         L              5               !       Bitwise OR
         L              5               ^       Bitwise EOR
         L              5               &       Bitwise AND

         L              4               <       Most significant byte
         L              4               >       Least significant byte

         -              3               <=      Less or equal
         -              3               >=      Greater or equal
         -              3               =       Equal
         -              3               <>      Not equal
         -              3               >       Greater than
         -              3               <       Less than

         L              2              .AND     Boolean AND

         L              1              .OR      Boolean OR

         L              0               ,       Seperator

   D i r e c t i v e s

   1. A s s e m b l e r   D i r e c t i v e s

   .ALIGN <expr>
      This is a special directive, that only works in the relocatable
      mode and only if no code yet has been generated! The point is
      that you sometimes want to align code on a page boundary for
      example display lists or display list interrupt routines. 
      Aligns code to the next boundary given by <expr>.
      0x1  == word align   (2 bytes)
      0x3  == lword align  (4 bytes)
      0xFF == page align   (256 bytes)
         .align $FF

   .CALL <macroname> *** unimplemented, sorry ***
      This special directive may only be used IN macro definitions. It
      acts like a regular macro call, except that all the parameters of
      the macro, that does the call, are passed over to the newly called
         .macro x
            .dbyte %1,%2
         .macro y
            .call x
         y $0123,$4567
      produces, predictably, 01 23 45 67

      When NASM65 encounters this directive, the processing of source 
      code is preempted.

   .IF <bexpr>
      These directives provide the ability to selectively assemble some
      parts of the program and to leave some parts out. The use for this
      feature lies most importantly in macros as you can see in the
      supplied "MACROS.H65" file.
      This for example is the macro code, for the "generic" store
      absolute instruction. Actually only one of STA STX or STY will
      be assembled.
         .macro @stt
      @0 .= @a
         .if %0 = 2
      @0 .= %2
         .if  @0 = @a
            sta   %1
            .if @0 = @x
               stx   %1
               sty   %1
      Note that for .IF there has to be an .ENDIF and at most one .ELSE.

      Tells the assembler to "forget" all local labels up to this point.
      This means that the following will get you an error with a .LOCAL,

      ; Start of file
         jmp   :foo
      ; end of file

      whereas the second piece of code, will only work with the .LOCAL.
      Else you would have a doubly defined label.

      ; Start of file
      :loop  dex
             bne :loop
      :loop  inx
             bne :loop
      ; End of file

   .INCLUDE #<filename>
      Reads in the file specified by <filename> and treats this input as
      if it would have appeared in the original file. Technically you first
      .INCLUDE is your source!

   .ERROR  <string>
      Creates a user error. This is like any other error that NASM65
      generates, but you can supply the error string (required). This may
      be useful, when writing .MACROs and you want to check that certain
      values are in the required range. This feature isn't really all that
      useful as OSS thinks it is. The assembler catches for example
      missing parameter errors anyway. MAC65 did too...

   .MACRO  <macroname>
      All <lines> are saved in an internal buffer and released upon
      invocation of <macroname>. f.e.

      LEOPOLD = $1234
         lda   #0       ;; gets assembled as A9 00
         .macro  foo    ;; start of macro definition called "FOO"
          sta   LEOPOLD ;; this will not be assembled at this time
         .endm          ;; end of macro definition. Continue assembly
         nop            ;; NOP gives an EA
         foo            ;; Assembles now STA LEOPOLD into 8D 34 12

      The interesting thing about macros is that you can pass values to
      them. These are accessed with the % placeholder. Lets consider an
         ;; simple POKE … la ATARI BASIC  "POKE address,value"
         .macro poke
          lda   #%2     ;; %2 means value from second parameter
          sta   %1      ;; %1 means value from first  parameter
         ;; macro invocation
         poke  $4000,124   ;; will assemble as  LDA #124  STA $4000

      %0 contains the number of arguments passed to the macro.

      You can not only pass values but also strings to a macro. These
      are accessed with %$.
         .macro drop_printable
            .byte %$1,155,0      ;; Parameter %1 as string

         drop_printable "Foo"    ;; converts to .BYTE "Foo",155,0

      Parameters can have these four forms:
         %<value>      ;; <value> gives index of integer parameter
         %(<label>)    ;; value of label gives index of integer parameter
         %$<value>     ;; <value> gives index of string parameter
         %$(<label>)   ;; value of <label> gives index of string parameter
      No forward referencing is allowed with %[$](<label>). The label
      you use there must already be defined.
      Another example:
         .macro foo
      which .= %2       ;; use '.=' NOT '=' !!
         .byte %1
         .byte %$1
         .byte %(WHICH)
         .byte %$(WHICH)
      MAGIC = $12
         foo  MAGIC,4,"UNUSED","Hello"

      would be expanded to

      which .= 4       ;; which has value of 4
         .byte $12     ;; MAGIC (=$12) was passed as the first parameter
         .byte "MAGIC" ;; Yup! Useless but it works!
         .byte 5       ;; String length of "Hello World"
         .byte "Hello" ;; String of "Hello"

      Type D labels that appear in macro definitions can be reused again. 
      The next example will not give errors on compilation, since "LEO" is 
      reset every time foo is called.
         .macro foo
      leo   inx
            foo   ;; OK!
            foo   ;; OK!
      "LEO" is visible for code outside the macro after an invocation of
      "FOO". Forward references to labels in macros are OK! You should not
      put local variables in macros.

   .REPT <expr> <macroname> [parameter[,<parameter>]*]
      This is a recent addition to NASM65, inspired by the 68000 
      assemblers. It repeatedly calls a macro (optionally with parameters). 
      The <expr> contains the number of repetitions.
      Ex:   REPT 3 LSL.W $3000   ; calls the MACRO `LSL.W' 3 times

   .WARNING  <string>
      Creates a user warning. This is much more useful than the .ERROR
      directive. For instance in macros you can explain possible hazards.
      Ex:   .WARNING "The world comes to an end soon!"

   .ZEXT <label>
      If you want to link two files together that share zeropage labels
      and you don't want to use a central include file to share zero
      page symbols, as would be inconvenient for library files that
      already exist in assembled form, you need to declare in one file
      the zeropage labels as external and in the other file as linkable
      zeropage labels. As usual an example will clear up things...
      File #1:
            .ZEXT src         ;; tells NASM65 that src, dst
            .ZEXT dst         ;; are zeropage addresses.
                              ;; Call with amount to move in X
      move: ldy   #0          ;; this isn't a very good mover
      :loop lda   (src),y     ;; but this is just for illustrating
            sta   (src),y     ;; a point
            bne   :loop

      File #2:
      SRC==$F0                ;; == means declare as linkable zeropage


      start ldx   #56
            lda   #<ROM
            sta   SRC
            lda   #>ROM
            sta   SRC+1
            lda   #<RAM
            sta   DST
            lda   #>RAM
            sta   DST+1
            ldx   #16
            jmp   move

      When linking the values of SRC and DST of file #1 will be set to
      those of file #2.

   .ORG <value>
      This can only be used in the runnable mode to set the assembly
      program counter. f.e:
         lda   #0       ;; useless ditty in PAGE 6
         sta   $2F4

         .org  $3000    ;; main program in PAGE $30
         jsr   $600

         *=RUNAD        ;; let DOS start program @$3000
         .word $3000
      Using .ORG in the relocatable mode yields an error.

   2.  C o d e   p r o d u c i n g   d i r e c t i v e s

   .BYTE [+offset,][[<string>],[<expr>]]*  ;; incorrect! guess the meaning
      Deposits BYTE values in memory. Strings are treated as arrays
      of ATASCII characters. There is no '\0' implicitly appended
      after a string like in C.

   .SBYTE [+offset,][[<string>],[<expr>]]* ;; Comment as above
      Same as above, except that bytes are converted for direct screen
      representation. (if you wanted to poke "HELLO WORLD" directly
      into screen memory.)

   .CBYTE [+offset,][[<string>],[<expr>]]* ;; Comment as above
      Same as .BYTE except that the last byte of a <string> is EORed with
      $80. This is supposedly useful, when you wan't to check for EOS with

   .WORD <expr>[,<expr>]*                  ;; that's correct
      Deposits words (LSB MSB) in memory.

   .DBYTE <expr>[,<expr>]*
      Deposits 16Bit values in MSB LSB order.

   .FLOAT   <float>[,<float>]*
      Deposits floating point exprs into memory. Expressions are not
      allowed with floats. This is only kept in NASM65 for MAC65

   .DS      <expr>
      Reserves <expr> bytes of memory. Not that useful in relocatable
      mode (see elsewhere). This is quite like writing *=*+<expr>.
      .DS is a code producing directive in relocatable mode.

   3.  O b s o l e t e   D i r e c t i v e s

   .TITLE   <string>
   .PAGE    <string>
   .SET     <expr>,<expr>
   .OPT     [NO]<option>[,[NO]<option>]*
   .TAB     <expr>
      These are all obsolete. The SET directive had some influence on
      code generation, but is NOT SUPPORTED anymore.

   E r r o r s   a n d   W a r n i n g s
   These are some errors and warnings that may need a bit more 
   Error:   "Label still has open references"
      This could happen in a case like this:
      foo   .= s1 
         lda   foo
      foo   .= s2    ; ERROR
         lda   foo
      NASM65 is single pass. On line 1 FOO is set to a forward as of yet
      unknown reference. In line 3 the value in FOO is overwritten although,
      we didn't yet had a chance to resolve the earlier forward reference.
   Warning: "Some non PC-relative labels point into code"
      If you used any of these labels to access memory, you might
      get into trouble. If you used those labels for benign purposes
      such as those from STDDEF, you can ignore those warnings"

   "Expression must be preceded by '<' or '>'"  [relocatable only]
      This occurs when you tried to assemble either  .BYTE <expr>  or an
      immediate instruction like  ADC   #<expr> and <expr> is PC-relative.
      In this case you must specify, whether to use the MSB '<' or the
      LSB '>' of the value. 
         .BYTE B8       ;; **ERROR** B8 undefined -> PC-relative fwd ref
         .BYTE <B8      ;; OK!

   T h i n g s   y o u   s a w   e n c l o s e d   i n   ' < > '

   address  : means a PC-relative address like foo in "foo: inx".

   bexpr    : Boolean expression. 0 is considered to mean 'false' and
              everything else means 'true'.

   continued: Just means next line should actually stand where you found

   equate   : This is a label, that has come into existance via a '='

   expr     : Arithmetic expression, like 4 + 5, [2 .AND 4] * [300 & 20]

   filename : System dependent character-string, that represents a path
              to a file in your filesystem.
              f.e.   TOS   ..\mystuff\n65\foo.h65
                     UNIX  /usr/lib/n65/fo.h65
              A filename can contain any characters that are valid for
              your filesystem. Note that this will bring in a slight
              source incompatibility between systems!

   float    : Atari's own fun floating point format. 6 Bytes. BCD.
              Avoid! E.g.:  -3.123E+24, +23.0, 0.1E-1

   label    : A label is a character string that represents an address or
              a value. You define labels by putting them in the first
              column of your source code. f.e.
              label  = 45
                   - or -
              label  .= 2
                   - or -
              label  lda   #2    ;; here label gets the value of *
              Labels have the same characterwise restriction as

   lines    : zero or more lines of ASCII/ATASCII text.

   macroname: Any character string derived from the following character
              set [A-Z,a-z,0-9,$,@,_,.]. Cannot start of with a digit!

   operation: Either an arithmetic operation ( * + - & etc.) or a
              boolean operation (.AND .NOT etc.)

   option   : ­Obsolete! Any of the following list
                     (LIST CLIST OBJ MLIST XREF NUM EJECT)

   parameter: a macro parameter. In POKE 2300,23 the numbers 2300 and
              23 which are passed to the macro as arguments are called

   portable : Portability is a relative thing. NASM65 will probably go 
              belly up on anything with 7-Bit chars or EBCDIC.

   saddress : means a short PC-relative address that can't be used
              in another expression. For example the least
              significant of a PC-relative address is a saddress.

   source   : The <filename> of the source file.

   string   : Any number of characters enclosed inbetween >"<.

   value    : means numbers or non-PC-relative labels like
              STACK=$100 or expressions made of the two like
              4*5, STACK/4, 2*STACK, STACK-STACK+1...

   G l o s s a r y

   ACK       Acknowledgement

   ASCII     ASCII != EBCDIC. 7-bit really

   Assembler Go back to your wordprocessor, you are reading the wrong

   ATASCII   Atari extension of ASCII. 8-Bit

   BMI       ..            ..
   LDA       ....  6502  ....  What       LDA #<expr> = A9 ..
   STA       .... mnemos ....    else ?   STA <word>  = 8D .. ..
   NOP       ..            ..

   Byte      8 bits unsigned

   CR        Carriage Return, '\r',  ASCII  13

   EOS       End of string

   ICD       ? . Just as great as OSS. Hardware mostly though. Bought

   Linker    A program that produces an executable program from one
             or more object files and libraries of object files.

   LSB       Least significant byte of a word -> $12[34]
                          LSB MSB order would be [34]12

   LF        Linefeed, '\n',  ASCII 10

   MAC65     Assembler distributed by OSS.

   MSB       Most significant byte of a word  -> $[12]34
                           MSB LSB order would be [12]34

   OS        Operating System

   OSS       Optimized Systems Software. Makers of great Software for
             the Atari 8-Bit. You could buy their stuff eyes closed.

   PC        Program counter

   REF       Reference

   SPACE     Space, ' ', ASCII 32

   TAB       Tabulator, '\t', ASCII 9

   THANX     Thanks

   TOS       Takes up 192K ROM-space in the ST. Contains fragments of

   UNIX      An OS.

   WORD      16 bits 8 of them comprise the LSB the other 8 the MSB

   B U G S  ( k n o w n )
      There is a serious bug in the documentation, which doesn't properly
      follow thru with the distinction of <equate> and <label>.

      The assembler does not print linenumber and filename, when the
      error or warning occurred on the last line.
      The assembler does no checking for overflow of it's program
      buffer space (assuming that noone would assemble more than
      48K in one run anyway). There is a limit imposed on many
      data structures in the object file, by virtue of using unsigned
      integers instead of lwords. If ANYONE runs into problems please
      tell me, changing stuff to LWORDs isn't that big a deal, it just
      wastes more filespace.
      On UNIX systems all include files must start with a lowercase

   A C K S ,  R E F S  &  T H A N X    (n” special order)

      Werner (Ex-Meister)  fr moralische Untersttzung
      Dinadan              for porting this to the AMIGA and finding
                           some bugs, that escaped me
      J. Richter           for helping to debug the MSDOS code and lending 
                           me his KONTRON AT for a few days.
      Matthias Reichel     for making a valiant (and successful) attempt
                           at porting 2.0 to the PC
      Harbison/Steele      C - A Reference Manual Second Edition
      Poole/McNiff/Cook    Your Atari Computer
      Chadwick             Mapping the Atari
      Dripke               6502 Assembler Kurs fr Beginner
      OSS                  MAC/65¿ Manual
      Lawrow               MAC/65
      Wilkinson            Atari Basic Source Book (?)
      Van Halen            (everything 'xcept maybe OU812) read the
      Metallica            (everything) sources
      Megadeth             (RIP *GREAT*, SFSG...SW? PS...BWIB? *GREAT*) to
      Chris Poland         (RTM) find some
      Joe Satriani         (everything) of 
      Steve Vai            (P&W) the hidden
      The Police           (RDB TGH) capabilities
      David Lee Roth       (ALAE *WHOA*) like
      Steve Morse          (SS *MASTERPIECE*) in the
      Suicidal Tendencies  (LCR) linker (har har) (is that outdated? nat/92)
      Front 242            (*FBF*)
            for continous (I mean continous) entertainment