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:
here: deca
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