Developing Software in Assembly Language
Syntax
By Jonathan W. Valvano

     This article, which discusses assembly language programming, accompanies the book Embedded Microcomputer Systems: Real Time Interfacing published by Brooks-Cole 1999. This document has four overall parts
     Overview
     Syntax (fields, pseudo ops) (this document)
     Local variables
     Examples


Assembly Language Syntax
     Programs written in assembly language consist of a sequence of source statements. Each source statement consists of a sequence of ASCII characters ending with a carriage return. Each source statement may include up to four fields: a label, an operation (instruction mnemonic or assembler directive), an operand, and a comment. The following are examples of an assembly directive and a regular machine instruction.
PORTA  equ   $0000  ; Assembly time constant
Inp    ldaa  PORTA  ; Read data from fixed address I/O data port

An assembly language statement contains the following fields.
    Label Field can be used to define a symbol
    Operation Field defines the operation code or pseudo-op
    Operand Field specifies either the address or the data.
    Comment Field allows the programmer to document the software.

Sometimes not all four fields are present in an assembly language statement. A line may contain just a comment. The first token in these lines must begin with a star (*) or a semicolon (;). For example,
; This line is a comment
* This is a comment too
     * This line is a comment

Instructions with inherent mode addressing do not have an operand field. For example,
label  clra       comment
       deca       comment
       cli        comment
       inca       comment


Recommendation: For small programs, you enable automatic assembly colors. The editor will then color each field according to its type.

Recommendation: For large programs, you disable automatic assembly colors, because the system will run too slow. Instead, use the assembler to color the source code.

--------------------------------------------------------------------------------------
Label Field
The label field occurs as the first field of a source statement. The label field can take one of the following three forms:

A. An asterisk (*) or semicolon (;) as the first character in the label field indicates that the rest of the source statement is a comment. Comments are ignored by the Assembler, and are printed on the source listing only for the programmer's information. Examples:
* This line is a comment
; This line is also a comment

B. A white-space character (blank or tab) as the first character indicates that the label field is empty. The line has no label and is not a comment. These assembly lines have no labels:
       ldaa 0
       rmb  10


C. A symbol character as the first character indicates that the line has a label. Symbol characters are the upper or lower case letters a- z, digits 0-9, and the special characters, period (.), dollar sign ($), and underscore (_). Symbols consist of one to 15 characters, the first of which must be alphabetic or the special characters period (.) or underscore (_). All characters are significant and upper and lower case letters are distinct.

A symbol may occur only once in the label field. If a symbol does occur more than once in a label field, then each reference to that symbol will be flagged with an error. The exception to this rule is the set pseudo-op that allows you to define and redefine the same symbol. We typically use set to define the stack offsets for the local variables in a subroutine. For more information see the examples of local variables. Set allows two separate subroutines to re-use the same name for their local variables.

With the exception of the equ  = and set  directives, a label is assigned the value of the program counter of the first byte of the instruction or data being assembled. The value assigned to the label is absolute. Labels may optionally be ended with a colon (:). If the colon is used it is not part of the label but merely acts to set the label off from the rest of the source line. Thus the following code fragments are equivalent:
heredeca
      bne  here

      
here  deca
      bne  here


A label may appear on a line by itself. The assembler interprets this as set the value of the label equal to the current value of the program counter. A label may occur on a line with a pseudo-op.

The symbol table has room for at least 2000 symbols of length 8 characters or less. Additional characters up to 15 are permissible at the expense of decreasing the maximum number of symbols possible in the table.

--------------------------------------------------------------------------------------
Operation Field
     The operation field occurs after the label field, and must be preceded by at least one white-space character. The operation field must contain a legal opcode mnemonic or an assembler directive. Upper case characters in this field are converted to lower case before being checked as a legal mnemonic. Thus 'nop', 'NOP', and 'NoP' are recognized as the same mnemonic. Entries in the operation field may be one of two types:

Opcode. These correspond directly to the machine instructions. The operation code includes any register name associated with the instruction. These register names must not be separated from the opcode with any white-space characters. Thus 'clra' means clear accumulator A, but 'clr a' means clear memory location identified by the label 'a'. The available instructions depend on the microcomputer you are using

Directive. These are special operation codes known to the Assembler that control the assembly process rather than being translated into machine instructions. The pseudo-op codes supported by this assembler are

Group A Group B Group C meaning
org org .org Specific absolute address to put subsequent object code
= equ   Define a constant symbol
  set   Define or redefine a constant symbol
dc.b db fcb .byte Allocate byte(s) of storage with initialized values
  fcc   Create an ASCII string (no termination character)
dc.w dw fdb .word Allocate word(s) of storage with initialized values
dc.l dl   .long Allocate 32 bit long word(s) of storage with initialized values
ds ds.b rmb .blkb Allocate bytes of storage without initialization
ds.w   .blkw Allocate bytes of storage without initialization
ds.l   .blkl Allocate 32 bit words of storage without initialization
end end .end Signifies the end of the source code (TExaS ignores these)

 

 

--------------------------------------------------------------------------------------
Operand Field
     The operand field's interpretation is dependent on the contents of the operation field. The operand field, if required, must follow the operation field, and must be preceded by at least one white-space character. The operand field may contain a symbol, an expression, or a combination of symbols and expressions separated by commas. There can be no white-spaces in the operand field. For example the following two lines produce identical object code because of the space between data and + in the first line:
    ldaa  data  +  1
    ldaa  data

     The operand field of machine instructions is used to specify the addressing mode of the instruction, as well as the operand of the instruction. The following table summarizes the operand field formats.

Operand  Format  6811/6812example
no operand accumulator and inherent clra
<expression> direct, extended, or relative ldaa 4
#<expression> immediate ldaa #4
<expression>,R indexed with address register ldaa 4,x
<expr>,<expr> bit set or clear bset 4,#$01
<expr>,<expr>,<expr> bit test and branch brset 4,#$01,there
<expr>,R,<expr>,<expr> bit test and branch brset 4,x,#$01,there


The valid syntax of the operand field depends on the microcomputer. For a detailed explanation of the instructions and their addressing modes, see the help system with the TExaS application.

--------------------------------------------------------------------------------------
Expressions.
     An expression is a combination of symbols, constants, algebraic operators, and parentheses. The expression is used to specify a value that is to be used as an operand. Expressions may consist of symbols, constants, or the character '*' (denoting the current value of the program counter) joined together by one of the operators: + - * / % & | ^ .

     +  add
     -  subtract
     *  multiply
     /  divide
     %  remainder after division
     &  bitwise and
     |  bitwise or
     ^  bitwise exclusive or

Expressions may include parentheses and other expressions. Expressions are evaluated using the standard arithmetic precedence. Evaluation occurs left to right for multiple operations with the same precedence. Arithmetic is carried out in signed 32-bit twos-complement integer precision (on the IBM PC).

Precedence operation
Highest parentheses
2 unary + - ~
3 binary * / % &
lowest binary + - ^ |

 

     Each symbol is associated with a 16-bit integer value that is used in place of the symbol during the expression evaluation. The asterisk (*) used in an expression as a symbol represents the current value of the location counter (the first byte of a multi-byte instruction)

     Constants represent quantities of data that do not vary in value during the execution of a program. Constants may be presented to the assembler in one of four formats: decimal, hexadecimal, binary, or ASCII. The programmer indicates the number format to the assembler with the following prefixes:

    0x    hexadecimal, C syntax
    %    binary
    'c'    ASCII code for a single letter ‘c’

Unprefixed constants are interpreted as decimal. The assembler converts all constants to binary machine code and are displayed in the assembly listing as hexadecimal.

A decimal constant consists of a string of numeric digits. The value of a decimal constant must fall in the range 0-65535, inclusive. The following example shows both valid and invalid decimal constants:

VALID INVALID REASON INVALID
12 123456 more than 5 digits
12345 12.3 invalid character


A hexadecimal constant consists of a maximum of four characters from the set of digits (0-9) and the upper case alphabetic letters (A-F), and is preceded by a dollar sign ($). Hexadecimal constants must be in the range $0000 to $FFFF. The following example shows both valid and invalid hexadecimal constants:

VALID INVALID REASON INVALID
$12 ABCD no preceding "$"
$ABCD $G2A invalid character
$001F $2F018 too many digits


A binary constant consists of a maximum of 16 ones or zeros preceded by a percent sign (%). The following example shows both valid and invalid binary constants:

VALID INVALID REASON INVALID
%00101 1010101 missing percent
%1 %10011000101010111 too many digits
%10100 %210101 invalid digit


A single ASCII character can be used as a constant in expressions. ASCII constants are surrounded by a single quotes ('). Any character, except the single quote, can be used as a character constant. The following example shows both valid and invalid character constants:

VALID INVALID REASON INVALID
'*' 'VALID' too long


For the invalid case above the assembler will not indicate an error. Rather it will assemble the first character and ignore the remainder.

--------------------------------------------------------------------------------------
Comment Field
     The last field of an Assembler source statement is the comment field. This field is optional and is only printed on the source listing for documentation purposes. The comment field is separated from the operand field (or from the operation field if no operand is required) by at least one white-space character. The comment field can contain any printable ASCII characters.
     As software developers, our goal is to produce code that not only solves our current problem, but can serve as the basis of our future problems. In order to reuse software we must leave our code in a condition such that future programmer (including ourselves) can easily understand its purpose, constraints, and implementation. Documentation is not something tacked onto software after it is done, but rather a discipline built into it at each stage of the development. We carefully develop a programming style providing appropriate comments. I feel a comment that tells us why we perform certain functions is more informative than comments that tell us what the functions are. An examples of bad comments would be:
      clr  Flag    Flag=0
      sei          Set I=1
      ldaa $1003   Read PortC


These are bad comments because they provide no information to help us in the future to understand what the program is doing. An example of good comments would be:
      clr  Flag    Signifies no key has been typed
      sei          The following code will not be interrupted
      ldaa $1003   Bit7=1 iff the switch is pressed


These are good comments because they make it easier to change the program in the future.
     
Self-documenting code is software written in a simple and obvious way, such that its purpose and function are self-apparent. To write wonderful code like this, we first must formulate the problem organizing it into clear well-defined subproblems. How we break a complex problem into small parts goes a long way making the software self-documenting. Both the concept of abstraction (introduced in the last section) and modular code (to be presented in the next section) address this important issue of software organization.
     Maintaining software is the process of fixing bugs, adding new features, optimizing for speed or memory size, porting to new computer hardware, and configuring the software system for new situations. It is the MOST IMPORTANT phase of software development. My personal opinion is that flowchart charts or software manuals are not good mechanisms for documenting programs because it is difficult to keep these types of documentation up to date when modifications are made.
     We should use careful indenting, and descriptive names for variables, functions, labels, I/O ports. Liberal use of equ provide explanation of software function without cost of execution speed or memory requirements. A disciplined approach to programming is to develop patterns of writing that you consistently follow. Software developers are unlike short story writers. It is OK to use the same subroutine outline over and over again. In the following program, notice the following style issues:

     1) Begins and ends with a line of *'s
     2) States the purpose of the subroutine
     3) Gives the input/output parameters, what they mean and how they are passed
     4) Different phases (submodules) of the code delineated by a line of -'s

******************* Max *******************************
* Purpose: returns the maximum of two 16 bit numbers
* This subroutine creates three 16 bit local variables
* Inputs: Num1 and Num2 are two 16 bit unsigned numbers
*  passed in on the stack
* Output: RegX is the maximum of X,Y
* Destroyed: CCR
* Calling sequence
*
  ldx  #100
*  pshx    Num1 pushed on stack
*  ldx  #200
*  pshx     Num2 pushed on stack
*  jsr  Max
*  puly    Balance stack
*  puly    Result in RegX
First   set  0   The first 16 bit local variable
Second  set  2   The second 16 bit local variable
Result  set  4   The Maximum of first,second
Num1    set  12  Input parameter1
Num2    set  10  Input parameter2
Max  pshy        Save registers, that will be modified
* - - - - - - - - - - - - - - - - - - - - - - - - - - -
     
pshx        Allocate Result local variable
     
pshx        Allocate Second local variable
     
pshx        Allocate First local variable
* - - - - - - - - - - - - - - - - - - - - - - - - - - -
     
tsx            Create stack frame pointer
     
ldy  Num1,X
     
sty  First,X   Initialize First=Num1
     
ldy  Num2,X
     
sty  Second,X  Initialize Second=Num2
     
ldy  First,X
     
sty  Result,X  Guess that Result=First
     
cpy  Second,X
     
bhs  MaxOK     Skip if First>=Second
     
ldy  Second,X  Since First<Second
     
sty  Result,X  make Result=Second
MaxOK ldx Result,X  Return Result in RegX
* - - - - - - - - - - - - - - - - - - - - - - - - - - -
     
puly    Deallocate local variables
     
puly
     
puly
* - - - - - - - - - - - - - - - - - - - - - - - - - - -
     
puly    Restore registers
     
rts

****************** End of Max *****************************

--------------------------------------------------------------------------------------
Assembly Listing
     The assembler output includes an optional listing of the source program and an object files. The listing file is created when the TheList.RTF file is open.
     Each line of the listing contains a reference line number, the address and bytes assembled, and the original source input line. If an input line causes more than 8 bytes to be output (e.g., a long FCC directive), the additional bytes are included in the object code (S19 file or loaded into memory) but not shown in the listing. There are three assembly options, each can be toggled on/off using the Assembly->Options command.

(4) cycles shows the number of cycles to execute this instruction
[100] total gives a running cycle total since last org pseudo-op
{PPP} type gives the cycle type


The codes used in the cycle type are different for each microcomputer
     The assembly listing may optionally contain a symbol table. The symbol table is included at the end of the assembly listing if enabled. The symbol table contains the name of each symbol, along with its defined value. Since the set pseudo-op can be used to redefine the symbol, the value in the symbol table is the last definition.

--------------------------------------------------------------------------------------
Assembly Errors

Programming errors fall into two categories. Simple typing/syntax error will be flagged by the TExaS assembler as an error when the assembler tries to translate source code into machine code. The more difficult programming errors to find and remove are functional bugs that can be identified during execution, when the program does not perform as expected. Error messages are meant to be self-explanatory. The assembler has a verbose (see Assembler->Options command) mode that provides more details about the error and suggests possible solutions.

Assembler Error Types
1) Undefined symbol: Program refers to a label that does not exist
     How to fix: check spelling of both the definition and access
2) Undefined opcode or pseudo-op
     How to fix: check the spelling/availability of the instruction
3) Addressing mode not available
     How to fix: look up the addressing modes available for the instruction
4) Expression error
     How to fix: check parentheses, start with a simpler expression
5) Phasing Error occurs when the value of a symbol changes from pass1 to pass2
     How to fix: first remove any undefined symbols, then remove forward references
6) Address error
     How to fix: use org pseudo-op’s to match available memory.
Error diagnostic messages are placed in the listing file just after the line containing the error. If there is no TheList.RTF file, then assembly errors are reported in TheLog.RTF file. If there is neither TheList.RTF or TheLog.RTF files, then assembly errors are not reported.

--------------------------------------------------------------------------------------
Phasing errors
     A phasing error occurs during Pass 2 of the assembler when the address of a label is different than when it was previously calculated. The purpose of Pass 1 of the assembler is to create the symbol table. In order to calculate the address of each assembly line, the assembler must be able to determine the exact number of bytes each line will take. For most instructions, the number of bytes required is fixed and easy to calculate, but for other instructions, the number of bytes can vary. A phasing errors occur when the assembler calculates the size of an instruction different in Pass 2 than previously calculated in Pass 2. Sometimes a phasing error often occurs on a line further down in the program than where the mistake occurs. A phasing error usually results from the use of forward references. In this 6812 example the symbol "index" is not available at the time of assembling the ldaa index,x. The assembler incorrectly chooses the 2 byte IDX addressing mode version rather than the correct 3 byte IDX1 mode.
       ldaa  index,x
index  equ 100
;  ...
loop   ldaa #0

The listing shows the phasing error
Copyright 1999-2000 Test EXecute And Simulate
$0000 A6E064         ldaa  index,x
$0064         index  equ  100
            ;  ...
$0003 8600    loop   ldaa  #0
#####
Phasing error
This line was at address $0002 in pass 1, now in pass 2 it is $0003

***************Symbol Table*********************
index  $0064
loop  $0002
##### Assembly failed, 1 errors!

When the assembler gets to loop, the Pass 1 and Pass 2 values are off by one causing a phasing error at the loop ldaa #0 instruction. The solution here to simply put the index equ 100 first.

 

--------------------------------------------------------------------------------------
Assembler pseudo-op's

Pseudo-op's are specific commands to the assembler that are interpreted during the assembly process. A few of them create object code, but most do not. There are two common formats for the pseudo-op's used when developing Motorola assembly language. The TExaS assembler supports both categories. If you plan to export software developed with TExaS to another application, then you should limit your use only the psuedo-op's compatible with that application.

Group A is supported by Motorola's MCUez, HiWare and ImageCraft's ICC11 and ICC12
Group B is supported by Motorola's DOS level AS05, AS08, AS11 and AS12
Group C are some alternative definitions

Group A Group B Group C meaning
org org .org Specific absolute address to put subsequent object code
= equ   Define a constant symbol
  set   Define or redefine a constant symbol
dc.b db fcb .byte Allocate byte(s) of storage with initialized values
  fcc   Create an ASCII string (no termination character)
dc.w dw fdb .word Allocate word(s) of storage with initialized values
dc.l dl   .long Allocate 32 bit long word(s) of storage with initialized values
ds ds.b rmb .blkb Allocate bytes of storage without initialization
ds.w   .blkw Allocate bytes of storage without initialization
ds.l   .blkl Allocate 32 bit words of storage without initialization
end end .end Signifies the end of the source code (TExaS ignores these)

 

--------------------------------------------------------------------------------------
equ equate symbol to a value

     <label> equ <expression> (<comment>)
     <label> = <expression> (<comment>)

The EQU (or =) directive assigns the value of the expression in the operand field to the label. The equ directive assigns a value other than the program counter to the label. The label cannot be redefined anywhere else in the program. The expression cannot contain any forward references or undefined symbols. Equates with forward references are flagged with Phasing Errorsphasing_error.
In the following example, the local variable names can not be reused in another subroutine:
; MC68HC812A4
; *****binding phase***************
I    equ  -4
PT   equ  -3
Ans  equ  -1
; *******allocation phase *********
function pshx    save old Reg X
     
tsx         create stack frame pointer
     
leas -4,sp  allocate four bytes for I,PT,Result
; ********access phase ************
     
clr  I,x    Clear I
     
ldy  PT,x   Reg Y is a copy of PT
     
staa Ans,x  store into Ans
; ********deallocation phase *****
     
txs    deallocation
     
pulx   restore old X
     
rts

In the following example, the equ pseudo-op is used to define the I/O ports and to access the various elements of the linked structure.
* ***********Moore.RTF*********************
* Jonathan W. Valvano 7/18/98 10:54:28 PM
* Moore Finite State Machine Controller
* PC1,PC0 are binary inputs, PB1,PB0 are binary outputs

PORTB  equ  0x01
DDRB   equ  0x03
PORTC  equ  0x04
DDRC   equ  0x06
TCNT   equ  0x84  ; 16 bit unsigned clock, incremented each cycle
TSCR   equ  0x86  ; set bit 7=1 to enable TCNT
* Finite State Machine Controller
* C1,C0 are inputs B1,B0 are outputs
     
 org  $800  variables go in RAM
StatePt  rmb  2  Pointer to the current state
     
 org  $F000  Put in EEPROM so it can be changed
Out   equ  0  offset for output value
* 2 bit pattern stored in the low part of an 8 bit byte
Wait  equ  1  offset for time to wait
Next  equ  2  offset for 4 next states
* Four 16 bit unsigned absolute addresses
InitState  fdb  S1  Initial state
S1   fcb  %01  Output
     
fcb  5    Wait Time
     
fdb  S2,S1,S2,S3
S2   fcb  %10  Output
     
fcb  10   Wait Time
     
fdb  S3,S1,S2,S3
S3   fcb  %11  Output
     
fcb  20   Wait Time
     
fdb  S1,S1,S2,S1
     
org  $F800 programs go in ROM
Main lds   #$0C00
     
movb  #$FF,TSCR enable TCNT
     
ldaa  #%11111111
     
staa  DDRB B1,B0 are LED outputs
     
ldaa  #%00000000
     
staa  DDRC C1,C0 are switch inputs
     
ldx   InitState State pointer
     
stx   StatePt
* Purpose: run the FSM
* 1. Perform output for the current state
* 2. Wait for specified amout of time
* 3. Input from the switches
* 4. Go to the next state depending on the input
* StatePt is the current state pointer
FSM  ldx   StatePt  1. Do output
     
ldab  Out,x  Output value for this state in bits 1,0
     
stab  PORTB
     
ldaa  Wait,x  2. Wait in this state
     
bsr   WAIT
     
ldab  PORTC  3. Read input
     
andb  #$03   just interested in bits 1,0
     
lslb     2 bytes per 16 bit address
     
abx     add 0,2,4,6 depending on input
     
ldx   Next,x  4. Next state depending on input
     
stx   StatePt
     
bra   FSM
* Reg A is the time to wait (256 cycles each)
WAIT  tfr  a,b
     
 clra    RegD= number of cycles to wait
     
 addd TCNT  TCNT value at the end of the delay
Wloop cpd  TCNT  EndT-TCNT<0 when EndT<Tcnt
     
 bpl  Wloop
     
 rts
     
 org  $FFFE
     
 fdb  Main  reset vector

--------------------------------------------------------------------------------------
set equate symbol to a value

     <label> set <expression> (<comment>)

The SET directive assigns the value of the expression in the operand field to the label. The set directive assigns a value other than the program counter to the label. Unlike the equ pseudo-op, the label can be redefined anywhere else in the program. The expression should not contain any forward references or undefined symbols. The use of this pseudo-op with forward references will not be flagged with Phasing Errors.

In the following example, the local variable names could be reused in another subroutine:
; MC68HC812A4
; *****binding phase***************
I    set  -4
PT   set  -3
Ans  set  -1
; *******allocation phase *********
function  pshx    save old Reg X
     
tsx          create stack frame pointer
     
leas  -4,sp  allocate four bytes for I,PT,Result
; ********access phase ************
     
clr  I,x    Clear I
     
ldy  PT,x   Reg Y is a copy of PT
     
staa Ans,x  store into Ans
; ********deallocation phase *****
     
txs    deallocation
     
pulx   restore old X
     
rts


--------------------------------------------------------------------------------------
fcb Form Constant Byte

     (<label>) fcb <expr>(,<expr>,...,<expr>) (<comment>)
     (<label>) dc.b <expr>(,<expr>,...,<expr>) (<comment>)
     (<label>) db <expr>(,<expr>,...,<expr>) (<comment>)
     (<label>) .byte <expr>(,<expr>,...,<expr>) (<comment>)

The FCB directive may have one or more operands separated by commas. The value of each operand is truncated to eight bits, and is stored in a single byte of the object program. Multiple operands are stored in successive bytes. The operand may be a numeric constant, a character constant, a symbol, or an expression. If multiple operands are present, one or more of them can be null (two adjacent commas), in which case a single byte of zero will be assigned for that operand. An error will occur if the upper eight bits of the evaluated operands' values are not all ones or all zeros.
     A string can be included, which is stored as a sequence of ASCII characters. The delimitors supported by TExaS are " ' and \. The string is not terminated, so the programmer must explicitly terminate it. For example:
str1 fcb "Hello World",0

In the following finite state machine the fcb definitions are used to store outputs and wait times.
Out   equ  0  offset for output value
* 2 bit pattern stored in the low part of an 8 bit byte
Wait  equ  1  offset for time to wait
Next  equ  2  offset for 4 next states
* Four 16 bit unsigned absolute addresses
InitState  fdb  S1  Initial state
S1   fcb  %01  Output
     
fcb  5  Wait Time
     
fdb  S2,S1,S2,S3
S2   fcb  %10  Output
     
fcb  10  Wait Time
     
fdb  S3,S1,S2,S3
S3   fcb  %11  Output
     
fcb  20  Wait Time
     
fdb  S1,S1,S2,S1

--------------------------------------------------------------------------------------
fcc Form Constant Character String

     (<label>) FCC <delimiter><string><delimiter> (<comment>)

The FCC directive is used to store ASCII strings into consecutive bytes of memory. The byte storage begins at the current program counter. The label is assigned to the first byte in the string. Any of the printable ASCII characters can be contained in the string. The string is specified between two identical delimiters. The first non-blank character after the FCC directive is used as the delimiter. The delimitors supported by TExaS are " ' and \.

Examples:

LABEL1  FCC  'ABC'
LABEL2  fcc  "Jon Valvano "
LABEL4  fcc  /Welcome to FunCity!/

The first line creates the ASCII characters ABC at location LABEL1. Be careful to position the fcc code away from executable instructions. The assembler will produce object code like it would for regular instructions, one line at a time. For example the following would crash because after executing the LDX instruction, the 6811 would try to execute the ASCII characters "Trouble" as instructions.
     ldaa  100
     
ldx  #Strg
Strg fcc  "Trouble"

Typically we collect all the fcc, fcb, fdb together and place them at the end of our program, so that the microcomputer does not try to execute the constant data. For example
     ldaa  Con8
     
ldy  Con16
     
ldx  #Strg
     
bra  loop
* Since the bra loop is unconditional,
* the 6811 won't go beyond this point.
Strg   fcc  "No Trouble"
Con8   fcb  100
Con16  fdb  1000


--------------------------------------------------------------------------------------
fdb Form Double Byte

     (<label>) fdb <expr>(,<expr>,...,<expr>) (<comment>)
     (<label>) dc.w <expr>(,<expr>,...,<expr>) (<comment>)
     (<label>) dw <expr>(,<expr>,...,<expr>) (<comment>)
     (<label>) .word <expr>(,<expr>,...,<expr>) (<comment>)

The FDB directive may have one or more operands separated by commas. The 16-bit value corresponding to each operand is stored into two consecutive bytes of the object program. The storage begins at the current program counter. The label is assigned to the first 16-bit value. Multiple operands are stored in successive bytes. The operand may be a numeric constant, a character constant, a symbol, or an expression. If multiple operands are present, one or more of them can be null (two adjacent commas), in which case two bytes of zeros will be assigned for that operand.

In the following finite state machine the fdb definitions are used to define state pointers. E.g., the InitState and the four Next pointers.
Out   equ  0  offset for output value
* 2 bit pattern stored in the low part of an 8 bit byte
Wait  equ  1  offset for time to wait
Next  equ  2  offset for 4 next states
* Four 16 bit unsigned absolute addresses
InitState  fdb  S1  Initial state
S1   fcb  %01  Output
     
fcb  5    Wait Time
     
fdb  S2,S1,S2,S3
S2   fcb  %10  Output
     
fcb  10   Wait Time
     
fdb  S3,S1,S2,S3
S3   fcb  %11  Output
     
fcb  20   Wait Time
     
fdb  S1,S1,S2,S1

--------------------------------------------------------------------------------------
dc.l Define 32 bit constant

     (<label>) dc.l <expr>(,<expr>,...,<expr>) (<comment>)
     (<label>) dl <expr>(,<expr>,...,<expr>) (<comment>)
     (<label>) .long <expr>(,<expr>,...,<expr>) (<comment>)

The dl directive may have one or more operands separated by commas. The 32-bit value corresponding to each operand is stored into four consecutive bytes of the object program (big endian). The storage begins at the current program counter. The label is assigned to the first 32-bit value. Multiple operands are stored in successive bytes. The operand may be a numeric constant, a character constant, a symbol, or an expression. If multiple operands are present, one or more of them can be null (two adjacent commas), in which case four bytes of zeros will be assigned for that operand.

In the following finite state machine the dl definitions are used to define 32 bit constants.
S1  dl     100000,$12345678
S2  .long  1,10,100,1000,10000,100000,1000000,10000000
S3  dc.l  -1,0,1


--------------------------------------------------------------------------------------
org Set Program Counter to Origin

     org<expression> (<comment>)
     .org<expression> (<comment>)

The ORG directive changes the program counter to the value specified by the expression in the operand field. Subsequent statements are assembled into memory locations starting with the new program counter value. If no ORG directive is encountered in a source program, the program counter is initialized to zero. Expressions cannot contain forward references or undefined symbols.

The org statements in the following skeleton place the variables in RAM and the programs in EEPROM of a MC68HC812A4
* ********** <<Name>> ********************
     
org  $800  variables go in RAM
* <<globals defined with rmb's go here>>
     
org  $F000  programs in EEPROM
Main:  lds  #$0C00  initialize stack to RAM
* <<one time initializations go here>>
loop:
* <<repeated operations go here>>
     
bra  loop
* <<subroutines go here>>
     
org  $FFFE
     
fdb  Main  reset vector

--------------------------------------------------------------------------------------
rmb Reserve Multiple Bytes

     (<label>) rmb <expression> (<comment>)
     (<label>) ds <expression> (<comment>)
     (<label>) ds.b <expression> (<comment>)
     (<label>) .blkb <expression> (<comment>)

The RMB directive causes the location counter to be advanced by the value of the expression in the operand field. This directive reserves a block of memory the length of which in bytes is equal to the value of the expression. The block of memory reserved is not initialized to any given value. The expression cannot contain any forward references or undefined symbols. This directive is commonly used to reserve a scratchpad or table area for later use.

--------------------------------------------------------------------------------------
ds.w Reserve Multiple Words

     (<label>) ds.w <expression> (<comment>)
     (<label>) .blkw <expression> (<comment>)

The ds.w directive causes the location counter to be advanced by 2 times the value of the expression in the operand field. This directive reserves a block of memory the length of which in words (16 bit) is equal to the value of the expression. The block of memory reserved is not initialized to any given value. The expression cannot contain any forward references or undefined symbols. This directive is commonly used to reserve a scratchpad or table area for later use.

--------------------------------------------------------------------------------------
ds.l Reserve Multiple 32-bit Words

     (<label>) ds.l <expression> (<comment>)
     (<label>) .blkl <expression> (<comment>)

The ds.l directive causes the location counter to be advanced by 4 times the value of the expression in the operand field. This directive reserves a block of memory the length of which in words (32 bit) is equal to the value of the expression. The block of memory reserved is not initialized to any given value. The expression cannot contain any forward references or undefined symbols. This directive is commonly used to reserve a scratchpad or table area for later use.


--------------------------------------------------------------------------------------
end End of program (optional)

     end (<comment>)
     .end (<comment>)

The END directive signifies the end of the source code. The TExaS assembler will ignore these pseudo operation codes.

--------------------------------------------------------------------------------------
ASCII Character codes

           BITS 4 to 6

    0 1 2 3 4 5 6 7
  0 NUL DLE SP 0 @ P ` p
B 1 SOH DC1 : 1 A Q a q
I 2 STX DC2 ! 2 B R b r
T 3 ETX DC3 # 3 C S c s
S 4 EOT DC4 $ 4 D T d t
  5 ENQ NAK % 5 E U e u
0 6 ACK SYN & 6 F V f v
  7 BEL ETB ' 7 G W g w
T 8 BS CAN ( 8 H X h x
O 9 HT EM ) 9 I Y i y
  A LF SUB * : J Z j z
3 B VT ESC + ; K [ k {
  C FF FS , < L \ l ;
  D CR GS - = M ] m }
  E SO RS . > N ^ n ~
  F S1 US / ? O _ o DEL

 

--------------------------------------------------------------------------------------
S-19 Object code
     The S-record output format encodes program and data object modules into a printable (ASCII) format. This allows viewing of the object file with standard tools and allows display of the module while transferring from one computer to the next or during loads between a host and target. The S-record format also includes information for use in error checking to insure the integrity of data transfers.
     S-Records are character strings made of several fields that identify the record type, record length, memory address, code/data, and checksum. Each byte of binary data is encoded as a 2-character hexadecimal number: the first character representing the high-order 4 bits, and the second the low-order 4 bits of the byte.

The 5 fields that comprise an S-record are:
     1) Type S0, S1 or S9
     2) Record Length
     3) Address
     4) Code/Data
     5) Checksum

Eight types of S-records have been defined to accommodate various encoding, transportation, and decoding needs, but only three types are used in most Motorola microcontrollers. The S0 record is a title record containing the ASCII name of the file in the Code/Data field. The address field of this type is usually 0000. The S1 record is a data record containing the information to be loaded sequentially starting at the specified address. The S9 record is a end of file marker, and sometimes contains the starting address to begin execution. In an embedded microcomputer environment, the starting address must be programmed at the appropriate place. For most Motorola microcontrollers, the reset vector is the last two bytes of ROM or EEPROM.

The Record Length contains the count of the character pairs in the length record, excluding the type and record length.

For S0, S1, S9 record types, the Address field is a 4-byte value. For the S1 record type the address specifies where the data field is to be loaded into memory.

There are from 0 to n bytes in the Code/Data field. This information contains executable code, memory loadable data, or descriptive information.

The Checksum field is 2 ASCII characters used for error checking. The least significant byte of the one's complement of the sum of the values represented by the pairs of characters making up the record length, address, and the code/data fields. When generating a checksum, one adds (call the result sum) the record length, address and code/data field using 8 bit modulo arithmetic (ignoring overflows.) The checksum is calculated
     checksum = $FF - sum
When verifying a checksum, one adds (call the result sum) the record length, address code/data field and checksum using 8 bit modulo arithmetic (ignoring overflows.) The sum should be $FF.

Each record may be terminated with a CR/LF/NULL.

The following is a typical S-record module:

     S1130000285F245F2212226A000424290008237C2A
     S11300100002000800082629001853812341001813
     S113002041E900084E42234300182342000824A952
     S107003000144ED492
     S9030000FC

The module consists of four code/data records and an S9 termination record.

The first S1 code/data record is explained as follows:

     S1  S-record type S1, indicating a code/data record to be loaded/verified at a 2-byte address.

     13  Hex 13 (decimal 19), indicating 19 character pairs, representing 19 bytes of binary data, follow.

     00  Four-character 2-byte address field: hex address 0000, indicates location where the following data is to be loaded.

     The next 16 character pairs are the ASCII bytes of the actual program code/data

     2A  Checksum of the first S1 record.

The second and third S1 code/data records each also contain $13 character pairs and are ended with checksums. The fourth S1 code/data record contains 7 character pairs.

The S9 termination record is explained as follows:

     S9  S-record type S9, indicating a termination record.

     03  Hex 03, indicating three character pairs (3 bytes) to follow.

     00  Four character 2-byte address field, zeroes.  00

     FC  Checksum of S9 record.

This document has four overall parts
     Overview
     Syntax (fields, pseudo ops) (this document)
     Local variables
     Examples