Lab Manual Appendix

A-0: Motorola-to-GNU Assembly Conversion Chart

This document contains a summary of the differences between Motorola assembly code and GNU assembly code. It's important to note that there are (were) actually several varieties of Motorola HC11 assemblers—we have done our best to handle the most common varieties in this document. However, the GNU assembler accepts a mostly different format than all of the Motorola assemblers. This is a blessing in disguise: the reward for introducing a new format is that assembly for any platform is written in very much the same format when using the GNU assembler. You can use this document to get a feel for the difference between Motorola-style and GNU-style assembly syntax.

General Differences

Description Motorola Convention GNU Convention Notes

Whitespace

Each line of code in a Motorola assembly file is divided into four tab-separated sections:

[LABEL]	OPERATION	[OPERAND [...]]	[COMMENT]

LABEL is an optional label for the line. It may optionally be followed by a colon (see "Labels and colons.")

OPERATION is either an instruction (mnemonic) or a pseudo-op (directive).

OPERAND is an operand to an instruction. There may be any number of operands depending on the line's OPERATION.

COMMENT is an optional section. By convention, comments begin with a semicolon ;, but it is ignored as part of the comment.

If a line begins with *, the entire line is ignored by the assembler (see "Comments").

In GNU assembly code, whitespace serves as a separator, but like C or Java, the type and number of whitespace characters (tab or space) is not syntactically significant; whitespace should be used to improve code readability.

(none)

Comments

* Data storage declaration
	ORG	$00
i	RMB	1	; variable i
j	RMB	1	; variable j
k	RMB	1	; variable k
/* The data storage declaration
   section */
	.sect .data
i:	.byte	# variable i
j:	.byte	# variable j
k:	.byte	# variable j

The GNU assembler recognizes two varieties of comments:

  • The C-style /* multi-line block
    comment */
  • The shell-style
    # single-line comment

Labels and colons

  • Colons after labels are optional.
  • Labels can appear on a line by themselves.
  • Colons after labels are required.
  • Labels can appear on a line by themselves.

In the Motorola assemblers, colons after labels are optional. In code written for the Motorola assembler, the colon seems to be absent more often than it appears. However, colons are required after label names in GNU assembly code.

You may find it useful to use a label on a line by itself to increase code clarity. In particular, you might want to begin a large block of code with a label on a line by itself.

An example to illustrate colon usage follows:

/* Motorola label without colon */
instr1	ldaa	#0xff

/* Gnu label with colon */
instr2:	ldaa	#0xff

Specifying numeric bases

Prefix Base
% Binary (2)
@ Octal (8)
(none) Decimal (10)
$ Hexadecimal (16)
Prefix Base
0b or 0B Binary (2)
0 Octal (8)
(none) Decimal (10)
0x or 0X Hexadecimal (16)

When specifying an immediate value in assembly, use the prefixes indicated in the tables. Remember: octal values always start with a zero, so if you mean for a decimal value to be decimal, make sure it doesn't start with a zero.

Capitalization

  • All instructions (mnemonics) and pseudo-ops (directives) are capitalized.
  • Label names are often capitalized.
  • Memory addresses and other hexadecimal values are usually capitalized.
  • All instructions (mnemonics) and pseudo-ops (directives) are in lowercase.
  • Label name case is significant (like Java or C; Globals in C are translated directly to labels!).
  • Memory addresses and other hexadecimal values are in lowercase.

The GNU assembler does not actually care what case you use for anything in your assembly programs. The capitalization discussed in the tables to the left is simply the accepted convention. You may use whatever capitalization you want to. However, there are a few caveats:

  • First, you should obviously attempt to follow the GNU convention as closely as possible. That's why it's a convention: people are expected to follow it.
  • Second, the section names (e.g., .data and .text) must be lowercase for the assembler and linker to put everything where it belongs.
  • Finally, the main symbol, if defined in an assembly routine, must be named in lowercase. The linker expects to find a routine named exactly main.

Pseudo-op Assembler Directives

Motorola Directive GNU Directive Notes
	ORG	$8000
	.sect	.data

and

	.sect	.text

Instead of using the ORG directive, divide your assembly program into data and text sections. The data section will store global variables and the text section will store your program's code. Constants can go in either the data or text section; local variables should go on the stack.

PORTD	EQU	$08
	.equ	PORTD, 0x08

Use the .equ directive instead of EQU. The argument to .equ can be a number or a label name; this is similar to a #define statement in C. Imagine that, for this example, wherever the text PORTD occurred in your code, the replacement 0x08 would be substituted instead.

	END
	.end

The GNU assembler, like all present-day assemblers, is smart enough to figure out where the end of your program is. You don't need to explicitly give an END command. However, if you insist, you can use the .end directive. All instructions after END and .end are ignored by the assembler.

BUFFER	RMB	5
	.size	BUFFER,	5

or

BUFFER:	.byte
	.byte
	.byte
	.byte
	.byte

Use the .size directive to reserve a chunk of memory for later use. The first argument to .size is the name of the label you want to associate with the beginning of the chunk of memory and the second argument is the number of bytes you want to reserve.

You can also use the .byte directive to reserve a byte of memory. The advantage to using .byte is that you can initialize the reserved bytes to some value: simply use the value as the argument to the .byte directive. For example, to initialize the first byte of BUFFER to 0: BUFFER: .byte 0x00.

BUFFER	BSZ	5
BUFFER:	.byte	0x00
	.byte	0x00
	.byte	0x00

or

BUFFER:	.byte	0x00, 0x00, 0x00

You must use the .byte directive to initialize a byte of memory to some value while reserving it.

ABC	FCB	$11, $22, $33
ABC:	.byte	0x11, 0x22, 0x33

Use the .byte directive to reserve and initialize bytes of memory.

ABC	FDB	$11,$22,$33
ABC:	.word	0x11, 0x22, 0x33

Use the .word directive to reserve and initialize words of memory. On the HC11, a word is two bytes (16 bits).

ALPHA	FCC	"DEF"
ALPHA:	.string	"DEF"

Use the .string directive to reserve memory and initialize it with a string value. This is slightly different than the Motorola assembler's FCC pseudo-op, however: the GNU assembler terminates strings with a null character (0). Therefore, ALPHA: .string "DEF" actually reserves four bytes of memory: three for the characters D, E, and F, and one for the null character.

SPACE	DCB	5,$20

or

SPACE	RMB	5
	FILL	$20,5

(depending on the assembler's syntax)

SPACE:	.byte	0x20
	.byte	0x20
	.byte	0x20
	.byte	0x20
	.byte	0x20

Instead of using the DCB or FILL directive, use the .byte directive with the GNU assembler.

HC11 Instructions Recognized by the GNU Assembler

The GNU assembler can print the full set of instructions it recognizes:

m6811-elf-as --print-opcodes | less

This list follows below:

aba   
abx   
aby   
adca    [#<imm8>]  [*<abs8>]  [<abs>]  [<imm8>,X]  [<imm8>,X]
adcb    [#<imm8>]  [*<abs8>]  [<abs>]  [<imm8>,X]  [<imm8>,X]
adda    [#<imm8>]  [*<abs8>]  [<abs>]  [<imm8>,X]  [<imm8>,X]
addb    [#<imm8>]  [*<abs8>]  [<abs>]  [<imm8>,X]  [<imm8>,X]
addd    [#<imm16>]  [*<abs8>]  [<abs>]  [<imm8>,X]  [<imm8>,X]
anda    [#<imm8>]  [*<abs8>]  [<abs>]  [<imm8>,X]  [<imm8>,X]
andb    [#<imm8>]  [*<abs8>]  [<abs>]  [<imm8>,X]  [<imm8>,X]
asl     [<abs>]  [<imm8>,X]  [<imm8>,X]
asla  
aslb  
asld  
asr     [<abs>]  [<imm8>,X]  [<imm8>,X]
asra  
asrb  
bcc     [<label>]  [<label>]
bclr    [*<abs8> #<mask>]  [<imm8>,X #<mask>]  [<imm8>,X #<mask>]
bcs     [<label>]  [<label>]
beq     [<label>]  [<label>]
bge     [<label>]  [<label>]
bgnd  
bgt     [<label>]  [<label>]
bhi     [<label>]  [<label>]
bhs     [<label>]  [<label>]
bita    [#<imm8>]  [*<abs8>]  [<abs>]  [<imm8>,X]  [<imm8>,X]
bitb    [#<imm8>]  [*<abs8>]  [<abs>]  [<imm8>,X]  [<imm8>,X]
ble     [<label>]  [<label>]
blo     [<label>]  [<label>]
bls     [<label>]  [<label>]
blt     [<label>]  [<label>]
bmi     [<label>]  [<label>]
bne     [<label>]  [<label>]
bpl     [<label>]  [<label>]
bra     [<label>]  [<label>]
brclr   [*<abs8> #<mask> <label>]  [<imm8>,X #<mask> <label>]  [<imm8>,X #<mask> <label>]
brn     [<label>]  [<label>]
brset   [*<abs8> #<mask> <label>]  [<imm8>,X #<mask> <label>]  [<imm8>,X #<mask> <label>]
bset    [*<abs8> #<mask>]  [<imm8>,X #<mask>]  [<imm8>,X #<mask>]
bsr     [<label>]  [<label>]
bvc     [<label>]  [<label>]
bvs     [<label>]  [<label>]
cba   
clc   
cli   
clr     [<abs>]  [<imm8>,X]  [<imm8>,X]
clra  
clrb  
clv   
cmpa    [#<imm8>]  [*<abs8>]  [<abs>]  [<imm8>,X]  [<imm8>,X]
cmpb    [#<imm8>]  [*<abs8>]  [<abs>]  [<imm8>,X]  [<imm8>,X]
cmpd    [#<imm16>]  [*<abs8>]  [<abs>]  [<imm8>,X]  [<imm8>,X]
cmpx    [#<imm16>]  [*<abs8>]  [<abs>]  [<imm8>,X]  [<imm8>,X]
cmpy    [#<imm16>]  [*<abs8>]  [<imm8>,X]  [<abs>]  [<imm8>,X]
com     [<abs>]  [<imm8>,X]  [<imm8>,X]
coma  
comb  
cpd     [#<imm16>]  [*<abs8>]  [<abs>]  [<imm8>,X]  [<imm8>,X]
cpx     [#<imm16>]  [*<abs8>]  [<abs>]  [<imm8>,X]  [<imm8>,X]
cpy     [#<imm16>]  [*<abs8>]  [<imm8>,X]  [<abs>]  [<imm8>,X]
daa   
dec     [<imm8>,X]  [<abs>]  [<imm8>,X]
deca  
decb  
des   
dex   
dey   
eora    [#<imm8>]  [*<abs8>]  [<abs>]  [<imm8>,X]  [<imm8>,X]
eorb    [#<imm8>]  [*<abs8>]  [<abs>]  [<imm8>,X]  [<imm8>,X]
fdiv  
idiv  
inc     [<imm8>,X]  [<abs>]  [<imm8>,X]
inca  
incb  
ins   
inx   
iny   
jmp     [<abs>]  [<imm8>,X]  [<imm8>,X]
jsr     [*<abs8>]  [<abs>]  [<imm8>,X]  [<imm8>,X]
ldaa    [#<imm8>]  [*<abs8>]  [<abs>]  [<imm8>,X]  [<imm8>,X]
ldab    [#<imm8>]  [*<abs8>]  [<abs>]  [<imm8>,X]  [<imm8>,X]
ldd     [#<imm16>]  [*<abs8>]  [<abs>]  [<imm8>,X]  [<imm8>,X]
lds     [#<imm16>]  [*<abs8>]  [<abs>]  [<imm8>,X]  [<imm8>,X]
ldx     [#<imm16>]  [*<abs8>]  [<abs>]  [<imm8>,X]  [<imm8>,X]
ldy     [#<imm16>]  [*<abs8>]  [<abs>]  [<imm8>,X]  [<imm8>,X]
lsl     [<abs>]  [<imm8>,X]  [<imm8>,X]
lsla  
lslb  
lsld  
lsr     [<abs>]  [<imm8>,X]  [<imm8>,X]
lsra  
lsrb  
lsrd  
mul   
neg     [<abs>]  [<imm8>,X]  [<imm8>,X]
nega  
negb  
nop   
oraa    [#<imm8>]  [*<abs8>]  [<abs>]  [<imm8>,X]  [<imm8>,X]
orab    [#<imm8>]  [*<abs8>]  [<abs>]  [<imm8>,X]  [<imm8>,X]
psha  
pshb  
pshx  
pshy  
pula  
pulb  
pulx  
puly  
rol     [<abs>]  [<imm8>,X]  [<imm8>,X]
rola  
rolb  
ror     [<abs>]  [<imm8>,X]  [<imm8>,X]
rora  
rorb  
rti   
rts   
sba   
sbca    [#<imm8>]  [*<abs8>]  [<abs>]  [<imm8>,X]  [<imm8>,X]
sbcb    [#<imm8>]  [*<abs8>]  [<abs>]  [<imm8>,X]  [<imm8>,X]
sec   
sei   
sev   
staa    [<abs>]  [*<abs8>]  [<imm8>,X]  [<imm8>,X]
stab    [<abs>]  [*<abs8>]  [<imm8>,X]  [<imm8>,X]
std     [<abs>]  [*<abs8>]  [<imm8>,X]  [<imm8>,X]
stop  
sts     [<abs>]  [*<abs8>]  [<imm8>,X]  [<imm8>,X]
stx     [<abs>]  [*<abs8>]  [<imm8>,X]  [<imm8>,X]
sty     [<abs>]  [*<abs8>]  [<imm8>,X]  [<imm8>,X]
suba    [#<imm8>]  [*<abs8>]  [<abs>]  [<imm8>,X]  [<imm8>,X]
subb    [#<imm8>]  [*<abs8>]  [<abs>]  [<imm8>,X]  [<imm8>,X]
subd    [#<imm16>]  [*<abs8>]  [<abs>]  [<imm8>,X]  [<imm8>,X]
swi   
tab   
tap   
tba   
test  
tpa   
tst     [<abs>]  [<imm8>,X]  [<imm8>,X]
tsta  
tstb  
tsx   
tsy   
txs   
tys   
wai   
xgdx  
xgdy  

You will notice that there are several possible operands accepted by each instruction. Of course, the possible operands accepted depend on the instruction—refer to your textbook for details. A description of each possible operand follows:

To see an example of each instruction used with each possible operand type, run the command m6811-elf-as --generate-example | less. While this information is used for GNU's debugging purposes, you may still find it useful.


A-0: Motorola-to-GNU Assembly Conversion Chart A-1: Commonly Used UNIX Commands