Assembly Syntax Overview

From Intellivision Wiki
Revision as of 07:53, 4 December 2010 by Mr z (talk | contribs) (Protected "Assembly Syntax Overview" ([edit=autoconfirmed] (indefinite) [move=autoconfirmed] (indefinite)))
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

This offers a brief overview of assembly syntax as implemented in as1600. Please refer to the official documentation for complete details: as1600.pdf and as1600.txt

Basic Format

Assembly code is a line oriented language, similar to languages like BASIC, FORTRAN, COBOL and many scripting languages. Each assembly code line divides into 4 major components:

or directive
foo:MOVRR0, R1; Copy R0 to R1


Labels always start in the first column. Labels give a name to an address or a value. The assembler resolves labels into numbers when it assembles the program. There are two sorts of labels:

  • Global labels. These start with one of these characters— a-zA-Z!&_^~. —followed by zero or more of these: 0-9a-zA-Z!&_^~. Examples: "FOO", "abc", "_a1", ".blah".
  • Local labels. These start with two @ signs, such as "@@loop". These labels are local to a PROC section. See the PROC directive below.

Other properties of labels:

  • Labels must have distinct names from instruction mnemonics, directives and operators (defined below).
  • Labels optionally may be followed by a colon or by white space. That is, both "foo" and "foo:" are allowed.

Labels are optional in most cases. Some directives, such as PROC, EQU and SET require a label.

Instructions and Directives

The next field is the instruction/directive field. Instructions and directives are always preceded by at least one white-space character, or a label with a colon. The CP1610 page lists all of the instructions.

Operand Order

Many instructions have two operands. In CP1610 assembly code, the last operand is generally the "destination" of the result, and the operands before it are "sources." For example:

   ADDR R0, R1  ; Compute "R0 + R1" and put the result in "R1".

A couple instructions, like JSR don't quite fit that model:

   JSR R5, foo  ; Jump to "foo", and put return address in "R5."

Common Directives

  • ROMW: Sets the current "ROM width." In most cases, you can use "ROMW 16", which is also the default. Set this once per program.
  • ORG: Sets the current "origin," that is, the address that the assembler is currently assembling at.
  • INCLUDE: Copies in an outside file into the current assembly. Makes it easy to factor a large program into many files.
  • PROC / ENDP: These define sections of code. They are useful primarily for defining a scope for local variables. Must be used with a label.
  • DECLE: Outputs one or more words of data to the ROM. Can be followed by comma separated expressions and strings. STRING is a synonym.
  • BIDECLE: Similar to DECLE, except it writes words as pairs of bytes. For each word, it writes the lower byte first and the upper byte second. It's most useful with data read using SDBD.
  • EQU: Sets a label to a value, and therefore must be used with a label. Often useful for giving meaningful names to memory locations and other constants. Values set by EQU cannot be changed.
  • SET: Similar to EQU, except that the value assigned to the label can be changed later. This can be useful with the REPEAT directive to compute complicated expressions.
  • REPEAT / ENDR: Repeats a block of code multiple times. The repeated code is merely replayed for the assembler as if you had cut and pasted it the specified number of times. Useful for unrolling loops or computing complicated expressions at assembly time.
  • IF / ELSE / ENDI: Conditional assembly directives. Useful for guarding pieces of code from being assembled, or otherwise controlling the assembly process based on the values of some labels.

The example at the end shows each of these in use.


PROC sections bear special mention. PROC is short for "procedure." The PROC directive indicates the start of a "local" name space. Local labels, those starting with "@@", become local to that section. Within that section, those labels may be referred to by their "@@" name.

Local labels also get a corresponding global name. The assembler strips off the @@, and prepends the PROC's name and a period. This makes it easy to refer to a PROC's local labels, and a handy way of grouping sets of names.


;; Loop 42 times and return
        MVII    #42,  R0
@@loop: DECR    R0
        BNEQ    @@loop

        JR      R5

;; Loop 57 times and return
        MVII    #57,  R0
        B       FOO.loop   ; Reuse FOO's loop.

In this example, the branch in FOO refers the local label "@@loop" by its local name. The branch in BAR refers to the same label by its global name, "FOO.loop".


Comments are optional, but recommended. Comments start with a semicolon ';', and end at the end of the line. Comments can start anywhere on a line, including the first column.


Expressions are mathematical statements consisting of one or more numbers or labels, connected by various operators. Most expressions evaluate down to a single value. One special case is the "string expression", which expands to a list of words. String expressions are only valid in a limited number of contexts.

Numeric Formats

The assembler accepts numbers in four basic formats:

Decimal12345Uses digits 0 - 9. Must not start with 0 unless the value is exactly 0.
Octal0377Uses digits 0 - 7. Always starts with a leading 0.
Hexadecimal$5A3CUses digits 0 - 9, A - F. Case insensitive. Starts with $.
Binary%01011010Uses digits 0, 1. Starts with %.


Strings are quoted expressions. They may be used directly with DECLE, BIDECLE, STRING and BYTE directives, or as an argument to the ASC() and STRLEN() operators. Characters within strings may be escaped using the backslash \. See the as1600 documentation for more details.

When used with DECLE, BIDECLE, STRING and BYTE directives, strings may be intermixed with other expressions, separated by commas. A common use for this is to terminate strings with a NUL (0) character.


    DECLE  "Hello World!", 0
    STRING "Hello World!", 0  ; synonymous with previous line


The following table lists some common operators that appear in expressions. This list is not exhaustive. Please refer to the as1600 documentation for a complete list.

MODModulo (remainder)
SHLShift left
SHRShift right
ANDBitwise logical AND
ORBitwise logical OR
XORBitwise logical XOR
NOTBitwise "NOT"
>GTGreater Than (signed)
>=GEGreater Than or Equal (signed)
<LTLess Than (signed)
<=LELess Than or Equal (signed)
<>NENot Equal
ASC("string",index)Returns ASCII code of indexed character
STRLEN("string")Returns the length of a string
DEFINEDReturns 1 if symbol is defined at this point (first pass)

Forward References

Expressions are computed at assembly time, which makes them a powerful method for computing complex values that will be fixed at run-time. This means that the values for all labels that appear in the expression must be known at assembly time. Expressions may include forward references, meaning references to labels whose values are not yet known. This is usually ok, since the assembler makes a second pass to finish computing these expressions. Certain directives, such as IF, EQU and REPEAT, need to know the exact value of the expression when the directive is reached the first time, though. The assembler will inform you if you use an expression whose value can't be computed when it needs it.


        ; This code has legal forward references.  The assembler will accept these:
TABLE   DECLE   (FOO AND $7F8) SHR 3, ((FOO AND $FC00) SHR 11) OR ((FOO AND $3) SHL 5)
        DECLE   (BAR AND $7F8) SHR 3, ((BAR AND $FC00) SHR 11) OR ((BAR AND $3) SHL 5)
        ; ... more code here
        ; ... more code here
        ; This code, however, does not have legal forward references.  
        ; The assembler will give an error for each EQU directive:
CST1    EQU     (FOO AND $7F8) SHR 3, ((FOO AND $FC00) SHR 11) OR ((FOO AND $3) SHL 5)
CST2    EQU     (FOO AND $7F8) SHR 3, ((FOO AND $FC00) SHR 11) OR ((FOO AND $3) SHL 5)
        ; ... more code here
        ; ... more code here

Also, the assembler will issue a warning if you have a forward reference to an EQU or SET directive. It's usually safe to ignore the warnings for EQU directives, but not for SET directives if the label's value gets SET more than once. The following examples trigger warnings:

        ; This triggers a warning that's probably safe to ignore, but still worth fixing.
        DECLE   FOO, BAR, BAZ

        ; ... more code here

FOO     EQU     42
BAR     EQU     17
BAZ     EQU     23
        ; This also triggers a warning, and may not do what the programmer intended
        DECLE   FOO

        ; ... more code here

FOO     SET      42    ;\
FOO     SET      17    ; |- Which of these gets used in the DECLE above?
FOO     SET      23    ;/


Expressions are computed with 32-bit precision. This makes it easy to do extended precision work. If you try to use a 32-bit value as an operand to an instruction or one of the data directives (e.g. DECLE), though, the assembler will complain that the value is out of range. The assembler allows 32-bit values in the range $FFFF8000 (-32768) to $0000FFFF (+65535) to silently truncate to 16 bits—that is, they will truncate without an error.


MAGIC   EQU     $4A5A6A7A            ; Set up magic 32-bit constant

        DECLE   MAGIC                ; Causes an error
        DECLE   MAGIC AND $FFFF      ; Valid
        DECLE   MAGIC SHR 16         ; Also valid

        MVII    #MAGIC, R0           ; Causes an error
        MVII    #MAGIC AND $FFFF, R0 ; Valid
        MVII    #MAGIC SHR 16, R0    ; Also valid

NUM1    EQU     $FFFF8000            ; -32768 as a 32-bit number
NUM2    EQU     $00008000            ; +32768 (unsigned) as a 32-bit number

        MVII    #NUM1, R0            ; sets R0 to $8000
        MVII    #NUM2, R0            ; also sets R0 to $8000

(Note: Older versions of as1600 will give an error on any values outside the range of $00000000 - $0000FFFF. Upgrade to the latest as1600 to fix this.)


The following (largely nonsensical) example shows many of the above basic features in use.

        ROMW    16    ; Set ROM width to 16-bit
        ORG     $5000 ; Begin assembling code at location $5000

ROW     EQU     10    ; Row to display copyright on
COL     EQU     1     ; Column to begin displaying copyright in

; EXEC-friendly ROM header.
ROMHDR: BIDECLE ZERO            ; MOB picture base   (points to NULL list)
        BIDECLE ZERO            ; Process table      (points to NULL list)
        BIDECLE MAIN            ; Program start address
        BIDECLE ZERO            ; Bkgnd picture base (points to NULL list)
        BIDECLE ONES            ; GRAM pictures      (points to NULL list)
        BIDECLE TITLE           ; Cartridge title/date
        DECLE   $03C0           ; Flags:  No ECS title, run code after title,
                                ; ... no clicks
ZERO:   DECLE   $0000           ; Screen border control
        DECLE   $0000           ; 0 = color stack, 1 = f/b mode
ONES:   DECLE   1, 1, 1, 1, 1   ; Color stack initialization

TITLE   DECLE   107, "Hello World!", 0  

MAIN    PROC    ; Start a PROC/ENDP section

        EIS                     ; Enable interrupts

        CALL    PRINT.FLS
        DECLE   7                    ; 7 is the color number for "white"
        DECLE   $200 + ROW*20 + COL  ; Expression, including labels
        DECLE   "  Copyright 2007  ", 0

    ; The following piece of code is disabled
    IF 0   
        MVII    #1234,  R0

        ; Copy 8 words from $120 to $128 quickly
        MVII   #$120,   R4
        MVII   #$128,   R5

        REPEAT 8
        MVI@   R4,      R0
        MVO@   R0,      R5

        ; Spin forever:
@@loop  B      @@loop            ; Branches to local "@@loop" label, aka "MAIN.loop"
        ENDP   ; Close a PROC/ENDP section

        INCLUDE "print.asm"