Repository navigation
Assembler Syntax
Normative source: SPRU018D, chapter 3 (sections 3.6 through 3.13). This page describes the syntax of an assembler source statement, the constant and symbol forms the assembler accepts, how expressions are evaluated, what the source and cross-reference listings contain, and the enhanced instruction forms.
A source program is a sequence of source statements. A statement may hold an assembler directive, a machine instruction, a macro directive, or a comment. The assembler reads up to 200 characters of each line; a longer line is truncated and a warning is issued.
A source statement is made of four ordered fields. Only the position of the first field is fixed; the rest are separated by whitespace. The general form:
[label][:] mnemonic [operand list] [;comment]
Column and whitespace rules:
- Every statement must start with one of: a label, a blank, an asterisk, or a semicolon.
- A label, when present, must start in column 1.
- At least one blank separates each field. A tab counts as a blank.
- A comment is optional. In column 1 it may open with an asterisk or a semicolon; anywhere past column 1 it must open with a semicolon.
The four fields of a line:
col 1
|
v
+----------+---+-----------+----------------+--------------------+
| label | : | mnemonic | operand list | ;comment |
+----------+---+-----------+----------------+--------------------+
starts in must NOT opcode, optional, runs to
column 1, start in directive, end of line; begins
colon column 1 macro call or with ; (or * only
optional (else read macro directive; in column 1)
as a label) operands are
comma-separated
Example statements:
SYM1 .set 2 ; Symbol SYM1 = 2
Begin: LDPK SYM1 ; Load DP with 2
.word 016h ; Initialize a word with 016h
A label is optional for every machine instruction and for most (not all) directives. When used it begins in column 1 and holds up to 32 alphanumeric characters from A-Z, a-z, 0-9, underscore, and dollar sign. Labels are case sensitive and the first character may not be a digit. An optional trailing colon is allowed and is not part of the name. When there is no label, column 1 must hold a blank, a semicolon, or an asterisk.
A label takes the current value of the section program counter (SPC), so it points to the statement it sits on. A label alone on a line is a valid statement; it assigns the current SPC and so points to the instruction on the following line (the SPC is not advanced). This is equivalent to:
label .set $ ; $ is the current value of the SPC
The mnemonic follows the label and must not begin in column 1 (if it does, it is read as a label). It may be a machine instruction (such as ABS, MPYU, SPH), an assembler directive (such as .data, .list, .set), a macro directive (such as .macro, .var, .mexit), or a macro call.
The operands follow the mnemonic. An operand may be a constant, a symbol, or an expression built from constants and symbols. Operands are separated by commas.
A comment may start in any column and runs to the end of the line. It may hold any ASCII character, blanks included. Comments appear in the listing but have no effect on assembly. A line that is only a comment is valid; in column 1 it opens with a semicolon or an asterisk, elsewhere with a semicolon only. An asterisk is a comment marker only in column 1.
The assembler accepts six kinds of constant. Each is held internally as a 32-bit quantity and is not sign-extended, so 0FFH equals 00FF hex (255), not -1.
| Type | Form | Limits | Notes |
|---|---|---|---|
| Binary | up to 16 binary digits then B or b | right-justified, zero-filled if short | digits 0 and 1 |
| Octal | up to 6 octal digits then Q or q | digits 0 through 7 | |
| Decimal | string of decimal digits | -32,768 to 65,535 | |
| Hexadecimal | up to 4 hex digits then H or h | right-justified if short | must begin with a digit 0-9; digits 0-9, A-F, a-f |
| Character | one or two characters in single quotes | held as 8-bit ASCII | see section 2.1 |
| Assembly-time | a symbol given an absolute value by .set | see section 2.2 |
Worked examples:
| Written | Decimal | Hexadecimal | Kind |
|---|---|---|---|
00000000B |
0 | 0 | binary |
0100000b |
32 | 20 | binary |
01b |
1 | 1 | binary |
11111000B |
248 | 0F8 | binary |
10Q |
8 | 8 | octal |
100000Q |
32,768 | 8,000 | octal |
226q |
150 | 96 | octal |
1000 |
1000 | 3E8 | decimal |
-32768 |
-32,768 | 8,000 | decimal |
25 |
25 | 19 | decimal |
78h |
120 | 0078 | hexadecimal |
0FH |
15 | 000F | hexadecimal |
37ACh |
14,252 | 37AC | hexadecimal |
A character constant is one or two characters in single quotes, held as 8-bit ASCII. Each single quote that is part of the constant is written as two consecutive single quotes. A constant of two single quotes alone is valid and has the value 0. A single character is right-justified.
| Written | Meaning | Internal value |
|---|---|---|
'a' |
the character a | 61 hex |
'C' |
the character C | 43 hex |
'''' |
one single quote | 27 hex |
'' |
a null character | 00 hex |
A character constant is a single integer value; a character string (section 3) is a list of characters.
A symbol given a value by .set becomes a constant. To use it in an expression the assigned value must be absolute:
shift3 .set 3
LAC *,shift3,AR1
.set may also give a symbol a register name, making the symbol a synonym for the register:
AuxR1 .set AR1
LAC *,0,AuxR1
A character string is a run of characters in double quotes, held as 8-bit ASCII. A double quote that belongs to the string is written as two consecutive double quotes. The maximum length depends on the directive that uses the string.
| Written | Resulting string | Length |
|---|---|---|
"sample program" |
sample program | 14 |
"PLAN ""C""" |
PLAN "C" | 8 |
Character strings appear as filenames (for example .copy "filename"), section
names (.sect "section name"), data for .byte "charstring", and the operand
of .string.
A symbol serves as a label, a constant, or a substitution symbol. The name is up to 32 alphanumeric characters from A-Z, a-z, 0-9, dollar sign, and underscore. The first character may not be a digit and the name may not hold embedded blanks. Symbols are case sensitive (ABC, Abc, and abc are three symbols) unless the -c option overrides this. A symbol is known only during the assembly that defines it unless .global declares it external.
A symbol used as a label becomes a symbolic address tied to a program location. Labels used locally within a file must be unique. Mnemonic opcodes and directive names without the leading dot are valid label names. Labels may be operands of .global, .ref, .def, or .bss.
Symbols may be set to constant values with .set or with the
.struct/.tag/.endstruct directives, letting a meaningful name stand for a
value. Symbolic constants cannot be redefined. The -d assembler option
(dspa -dname=[value]) also equates a value with a symbol; if the value is
omitted the symbol is set to 1. Source can test such a symbol:
| Test | Directive usage |
|---|---|
| Exists | .if $isdefed("name") |
| Does not exist | .if $isdefed("name") = 0 |
| Equal to a value | .if name = value |
| Not equal to a value | .if name != value |
The argument to $isdefed must be quoted so it is taken literally rather than as a substitution symbol.
The assembler predefines several symbols:
-
$stands for the current value of the section program counter (SPC). - Register symbols: AR0-AR1 on the 'C1x, AR0-AR7 on the 'C2x/C2xx/5x.
- Port address symbols: PA0-PA7 on the 'C1x, PA0-PA15 on the 'C2x/C2xx/5x.
- Version symbols that steer code generation for a target processor, used with the version switch or the .version directive.
- Symbols brought in by the .mmregs directive.
Version symbols:
| Version symbol | -Version option | .version directive |
|---|---|---|
| .TMS32010 | -v10 | 10 |
| .TMS32016 | -v16 | 16 |
| .TMS32020 | -v20 | 20 |
| .TMS32025 | -v25 | 25 |
| .TMS3202XX | -v2xx | 29 |
| .TMS32050 | -v50 | 50 |
| .TMS320XX | processor version |
.TMS320XX holds the value of the version switch; invoking dspa -v20 filename
makes .TMS320XX equal 20, so .TMS32020 is true (1) and the other version
symbols are false (0).
Register symbol values differ by device. On 'C1x/C2x/C2xx the values are
AR0 = 0, AR1 = 1, and so on. On 'C5x they equal the memory-mapped addresses, so
the assembler reads the symbol by context: in ADD *+, AR7 the AR7 means 7,
while in ADD AR7 it is the address of AR7, which is 17.
A symbol may be assigned a string value, aliasing a character string to a name. When the assembler meets a substitution symbol it replaces the name with the string. Unlike symbolic constants, substitution symbols can be redefined. They are assigned with .asg anywhere in the program; macro parameters are substitution symbols that receive the macro arguments.
.asg "ar0", SP ; stack pointer
.asg "*+", INC ; indirect auto-increment
ADD label, INC, SP
A local label has the form $n, where n is a decimal digit 0-9 (for example
$4, $1). Unlike a normal label it may be undefined and defined again. A
local label is reset in any of four ways:
- the .newblock directive,
- changing sections with .sect, .text, or .data,
- entering an include file (.include or .copy),
- leaving an include file (.include or .copy).
Up to ten local labels may be in effect at once. After one is undefined it may be defined and used again. Local labels do not appear in the object code symbol table, which makes them useful inside macros that are called more than once: with a local label plus .newblock, the label is reset each expansion instead of raising a multiple-definition error.
Label1: lac a
sub b
blz $1
lac b
b $2
$1 lac a
$2 add c
.newblock ; undefine $1 so it can be reused
blez $1
sacl c
$1 nop
An expression is a constant, a symbol, or constants and symbols joined by arithmetic operators. Valid expression values range from -32,768 to 32,767. Three factors set the order of evaluation:
- Parentheses are always evaluated first;
8/(4/2)is 4 while8/4/2is 1. Braces and brackets may not stand in for parentheses. - Precedence groups: when parentheses do not decide the order, the
highest-precedence operator runs first;
8 + 4/2is 10. - Left-to-right: when neither parentheses nor precedence decide, evaluation runs
left to right, except group 1, which runs right to left;
8/4*2is 4 while8/(4*2)is 1.
Operators fall into four precedence groups, group 1 highest:
| Group | Operator | Description | Evaluation |
|---|---|---|---|
| 1 | + |
unary plus | right to left |
| 1 | - |
unary minus | right to left |
| 1 | ~ |
ones complement | right to left |
| 2 | * |
multiplication | left to right |
| 2 | / |
division | left to right |
| 2 | % |
modulo | left to right |
| 2 | << |
left shift | left to right |
| 2 | >> |
right shift | left to right |
| 3 | + |
addition | left to right |
| 3 | - |
subtraction | left to right |
| 3 | ^ |
bitwise exclusive-OR | left to right |
| 3 | | |
bitwise OR | left to right |
| 3 | & |
bitwise AND | left to right |
| 4 | < |
less than | left to right |
| 4 | > |
greater than | left to right |
| 4 | <= |
less than or equal to | left to right |
| 4 | >= |
greater than or equal to | left to right |
| 4 |
= or ==
|
equal to | left to right |
| 4 | != |
not equal to | left to right |
The assembler checks arithmetic for overflow and underflow at assembly time and issues a Value Truncated warning when either happens; it does not check multiplication. The group-4 relational operators are especially useful in conditional assembly. A conditional expression yields 1 if true and 0 if false, and may compare only operands of equivalent types (absolute with absolute, not absolute with relocatable).
Some directives require a well-defined expression: one built only from symbols
or assembly-time constants that are already defined where the expression
appears, and whose evaluation is absolute. For example 1000h+X is well
defined when X was previously defined as an absolute symbol.
An expression may not multiply or divide by a relocatable or external symbol, and may not hold unresolved symbols that are relocatable with respect to other sections. Symbols or registers made global with .global are called external here. Relocatable registers may appear in expressions; their addresses are relocatable with respect to the register section that defined them unless declared external.
The result type of addition and subtraction:
| A is | B is | A + B is | A - B is |
|---|---|---|---|
| absolute | absolute | absolute | absolute |
| absolute | external | external | illegal |
| absolute | relocatable | relocatable | illegal |
| relocatable | absolute | relocatable | relocatable |
| relocatable | relocatable | illegal | absolute (same section only) |
| relocatable | external | illegal | illegal |
| external | absolute | external | external |
| external | relocatable | illegal | illegal |
| external | external | illegal | illegal |
Subtracting one relocatable from another is absolute only when both are in the same section.
Every legal expression reduces to either relocatable symbol +/- absolute symbol or an absolute value. Unary operators apply only to absolute values,
never to relocatable symbols, and an expression that cannot be reduced to a
single relocatable symbol is illegal. Examples (extern_1 external, intern_1 and
intern_2 relocatable in the same section, LAB1 = 2 absolute):
LACK LAB1 + ((4+3) * 7) ; ACC = 51
LACK LAB1 + 4 + (3*7) ; ACC = 27
LACK extern_1 - 10 ; legal
LACK 10 - extern_1 ; illegal, cannot negate a relocatable
LACK -(intern_1) ; illegal, cannot negate a relocatable
LACK extern_1/10 ; illegal, / is not additive
LACK intern_1 + extern_1 ; illegal, two relocatables
LACK intern_1 - intern_2 + extern_1 ; legal
LACK intern_1 + intern_2 + extern_1 ; illegal
LACK intern_1 + extern_1 - intern_2 ; illegal (left to right adds two relocatables first)
Invoking the assembler with -l (lowercase L) produces a source listing that pairs each source statement with the object code it generates. Each page opens with two banner lines, a blank line, and a title line that carries any .title text and a page number. A source statement that produces several words of object code lists the extra SPC and object-code words on their own following lines. A listing line has four fields:
| Field | Contents |
|---|---|
| 1 Source statement number | decimal line number; the assembler may also prefix an include-file letter and a macro/loop nesting-level number. Some statements advance the counter without being listed, so a gap in the numbers counts the unlisted statements. |
| 2 Section program counter | hexadecimal SPC. Each section (.text, .data, .bss, named sections) keeps its own SPC. Directives that do not touch the SPC leave this blank. |
| 3 Object code | hexadecimal object code, with a trailing relocation-type character (see below). |
| 4 Source statement | the source characters as scanned, up to 200; spacing follows the source. |
Relocation-type characters appended to field 3:
| Character | Relocation |
|---|---|
! |
undefined external reference |
' |
.text relocatable |
" |
.data relocatable |
+ |
.sect relocatable |
- |
.bss or .usect relocatable |
^ |
.asect relocatable |
Invoking with -x (or the .option directive) appends a cross-reference listing to the source listing. It shows each symbol and its definition:
| Column | Contents |
|---|---|
| Label | every symbol defined or referenced during assembly |
| Value | a 4-digit hexadecimal value, or a name describing the symbol's attributes, optionally followed by an attribute character |
| DEFN | the statement number that defines the symbol; blank if undefined |
| REF | line numbers of statements that reference the symbol; blank if never used |
Symbol attribute characters and names in the Value column:
| Character or name | Meaning |
|---|---|
| REF | external reference (.global symbol) |
| UNDF | undefined |
' |
defined in a .text section |
" |
defined in a .data section |
+ |
defined in a .sect section |
- |
defined in a .bss or .usect section |
An enhanced instruction is a single mnemonic that stands in for several similar base instructions; these are valid on the 'C2x, 'C2xx, and 'C5x. The assembler reads the operands and picks the correct opcode. For example:
| Enhanced instruction | Base instruction |
|---|---|
ADD x |
ADD x |
ADD *+ |
ADD *+ |
ADD #100 |
ADDK 100 |
ADD #3000 |
ADLK 3000 |
ADD *+,16 |
ADDH *+ |
MIT - (c) 2026 Grzegorz Worona grzegorz@worona.pl. See LICENSE.
Start here
The TMS320C5x processor
Writing assembly
The instruction set
A: ABS ADCB ADD ADDB ADDC ADDH ADDI ADDK ADDS ADDT ADLK ADRK AND ANDB ANDI ANDK APAC APL APLI APLK
B: B BACC BACCD BANZ BANZD BBNZ BBZ BC BCND BCNDD BD BDDD BDSD BGEZ BGZ BIOZ BIT BITT BKDK BLDD BLDP BLEZ BLKD BLKP BLPD BLZ BNC BNV BNZ BPSD BSAR BV BZ
C: CALA CALAD CALL CALLD CC CCD CLRC CMPL CMPR CNFD CNFP CONF CPL CPLI CPLK CRGT CRLT
E: EHWBS EHWBT EINT EMPSD EMRET ESTOP ESTPD ETRAP EXAR
F: FORT
L: LAC LACB LACC LACI LACK LACL LACT LALK LAMM LAR LARK LARP LDP LDPI LDPK LMMR LPH LRLK LST LST0 LST1 LT LTA LTD LTP LTS
M: MAC MACD MADD MADS MAR MPY MPYA MPYI MPYK MPYS MPYU MRKL
O: OPL OPLI OPLK OR ORB ORI ORK OUT
R: RC RET RETC RETCD RETD RETE RETI RFSM RHM ROL ROLB ROR RORB ROVM RPT RPTB RPTI RPTK RPTR RPTZ RSXM RTC RTXM RXF
S: SACB SACH SACL SAMM SAR SATH SATL SBB SBBB SBLK SBRK SC SETC SFL SFLB SFR SFRB SFSM SHM SMMR SOVM SPAC SPH SPL SPLK SPM SQRA SQRS SST SST0 SST1 SSXM STC STXM SUB SUBB SUBC SUBH SUBI SUBK SUBS SUBT SWI SXF
X: XC XOR XORB XORI XORK XPL XPLI XPLK
Building a program
The tools
Normative sources: TI SPRU056D and SPRU018D (see References).
License: MIT - (c) 2026 Grzegorz Worona.