68000 MACHINE LANGUAGE COURSE PART III by Mark van den Boer
In part I & II the basics of programming the 68000 have been
introduced. In the following parts of this course I will discuss
the instructions of the 68000. To understand this part and the
coming ones I suggest you keep a printed copy of part II (the
addressing modes) in close range, so you can look things up.
Before discussing the individual instructions of the 68000 I will
divide its instructions into eight classes.
These classes are:
- Data movement operations.
- Integer arithmetic operations (on two's complement binary
numbers.
- Logical operations.
- Shift and rotate operations.
- Bit manipulation operations.
- Binary Coded Decimal (BCD) operations.
- Program control instructions.
- System control operations.
In this part and the following parts all classes will be
discussed. This approach is somewhat different of the one chosen
by other authors (the alphabetic order). For an explanation of
the source and destination addressing modes I refer to the table
at the end of part II.
To specify the operands of the instructions the following
conventions are used:
Rn stands for either a data- or addressregister
An stands for an address register
Dn stands for a data register
<ea> stands for an effective address operand. This means that
after the operand after evaluation must yield an address.
# stands for immediate data
All other symbols which appear in either field of the
instruction's assembler syntax will be explained.
One suggestion before the explanation starts: Since 68000
instructions may operate on bytes, words and longwords, it is
wise to always specify which size you want to manipulate. This
way will considerably reduce the amount of very hard to find bugs
in your program. Since assemblers take defaults when no size is
specified you can get very odd results. E.g. BSET (instruction
will be explained later) operates only on bytes and longwords.
The assembler makes the default for you. Suppose you want a word-
operation to be performed and you don't specify the size,
thinking that the default is nearly always word. Well in this
case the default isn't word, so the assembler thinks your code is
alright, but it doesn't do what you want.
Data movement operations
Instruction: EXG
Syntax: EXG Rn,Rn
Data sizes: Long
Condition codes affected: None
Addressing modes:
source: Dn
An
destination:
Dn
An
Function: Exchange the contents of two registers
Example:
Instruction Before After
EXG a0,d0 d0=11111111 d0=22222222
a0=22222222 a0=11111111
Instruction: LEA
Syntax: LEA <ea>,An
Data sizes: Long
Condition code affected: None
Addressing modes:
Source:
(An)
w(An)
b(An,Rn)
w
l
w(PC)
b(PC,Rn)
Destination:
An
Function: Load an address register with a value. LEA stands
for Load Effective Address.
Example:
Instruction Before After
LEA (a1),a0 a0=00000000 a0=12345678
a1=12345678 a1=12345678
LEA 9(a0),a0 a0=00111111 a0=00111119
LEA 5(a0,d0.w) a0=10000100 a0=10001111
d0=0000100b d0=0000100b
LEA $12345678,a0 a0=00000000 a0=12345678
Instruction: LINK
Syntax: LINK An,#
Data sizes: None
Condition codes affected: None
Addressing modes:
source: An
destination:
#w
Function: Create temporary space on stack. The source
(address register) is pushed onto the stack, the
stack-pointer (a7) is copied into the source and
the destination is added to the stack-pointer. The
destination-operand is usually negative because
the 68000-stack grows downward in memory. This
instruction is used very much by high-level
languages such as C and PASCAL. This instruction
has the advantage that local variables in a
subroutine can be accessed through the source-
address register.
E.g.: Every C-compiler on the Atari St uses this
instruction at the beginning of every subroutine.
Example:
Instruction Before After
LINK a6,#-4 a6=12345678 a6=44444444
a7=44444448 a7=44444440
Let's analyse: First a6 is pushed onto the stack: a7=44444444.
Then the stack-pointer is copied into a6. Then the
destination-operand is added to a7.
Instruction: UNLK
Syntax: UNLK source
Data sizes: None
Condition codes affected: None
Addressing modes:
source: An
Function: The opposite of LINK. Also used by all C-compilers
at the end of functions.
Example:
For values see LINK
Instruction Before After
UNLK a6 a6=44444444 a6=12345678
a7=???????? a7=44444448
First a6 is copied into a7: a7=44444444. Then a6
is pulled from the stack, which yields the final
values of a6 and a7
Instruction: MOVE
Syntax: MOVE <ea>,<ea>
Data sizes: Byte, Word, Long
Condition codes affected: N,Z (conditionally set/cleared),
V,C (always cleared)
Addressing modes:
source: Dn
An
(An)
(An)+
-(An)
w(An)
b(An,Rn)
w
l
w(PC)
b(PC,Rn)
#x
destination:
Dn
(An)
(An)+
-(An)
w(An)
b(An,Rn)
w
l
Function: Move the contents of the source to the
destination. This instruction is the most
frequently used 68000-instruction and is very
powerful. Note that the PC-relative addressing
modes are not allowed as destination-operand. This
seems illogical, but there's a good reason for it.
In the view of the designers at Motorola it is bad
practice to have self-modifying code in a program.
Example:
See part II of this course for examples on the MOVE-instruction.
Instruction: MOVE to CCR
Syntax: MOVE <ea>,CCR
Data sizes: Byte
Condition codes affected: All as a direct result of the
instruction.
Addressing modes:
source: Dn
(An)
(An)+
-(An)
w(An)
b(An,Rn)
w
l
w(PC)
b(PC,Rn)
#x
Function: Set some condition codes. With this instruction you can
clear/set the N,Z,V,C and X flag.
Example: See part II
Instruction: MOVE to SR
Syntax: MOVE <ea>,SR
Data sizes: Word
Condition codes affected: All as a direct result of the
instruction. This instruction is priviliged .
Addressing modes:
source: Dn
(An)
(An)+
-(An)
w(An)
b(An,Rn)
w
l
w(PC)
b(PC,Rn)
#x
Function: Set condition codes.
Example: See part II
Instruction: MOVE from SR
Syntax: MOVE SR,<ea>
Data sizes: Word
Condition codes affected: None.
Addressing modes:
source: SR
destination:
Dn
(An)
(An)+
-(An)
w(An)
b(An,Rn)
w
l
Function: Request condition codes. This function is not
priviliged on the 68000 and 68008, but is priviliged on
all other members of the 68000-family.
Example: See part II
Instruction: MOVE to/from USP
Syntax: MOVE USP,An or MOVE An,USP
Data sizes: Long
Condition codes affected: None.
Addressing modes: see Syntax
Function: This instruction is priviliged. The instruction exists
because the 68000 has in fact two stack-pointers. They
are both contained in a7. This is possible because the
68000 has two modes of operation: user- and supervisor-
mode. When in usermode it is impossible to access the
supervisor stackpointer. It is rather logical that
there are in fact two stackpointers. If there had been
only one it would have been possible to mess up the
stack in such a way that the system would crash.
However, the supervisor must have the ability to access
the user-stackpointer (for parameter-passing etc.).
Example:
Instruction Before After
MOVE USP,a6 USP=12345678 USP=12345678
a6=33333333 a6=12345678
Instruction: MOVEA
Syntax: MOVEA <ea>,An
Data sizes: Word, Long
Condition codes affected: None
Addressing modes:
source: Dn
An
(An)
(An)+
-(An)
w(An)
b(An,Rn)
w
l
w(PC)
b(PC,Rn)
#x
destination:
An
Function: Load an address register with a value. If the operation
is word-sized then the address is sign-extended. Most
assemblers will accept MOVE <ea>,An as well. However, I
think it is better to write MOVEA instead of just MOVE.
When you intend to move a value into an address
register but you forget to specify an address register
and specify something else, the assembler will not
generate an error. E.g. you want to move $12345678 into
a0. MOVE.L #$12345678,d0 will not generate an error,
while MOVEA.L #$12345678,d0 will generate an error.
Example: See part II
Instruction: MOVEM
Syntax: MOVEM register list,<ea> or
MOVEM <ea>,register list
register list is a set of registers. Suppose you
want to specify all data-register. You could
write: d0-d7 or d0/d1/d2/d3/d4/d5/d6/d7 or d0-
d3/d4/d5-d7. A number of registers in a row can be
denotated with a minus ('-') between them. Single
registers can be specified with a slash ('/')
between them.
Data sizes: Word or Long
Condition codes affected: None
Addressing modes:
destination:
(An)
-(An)
w(An)
b(An,Rn)
w
l
source: (An)
(An)+
w(An)
b(An,Rn)
w
l
w(PC)
b(PC,Rn)
Example:
Instruction: Before After
MOVEM.W $1000,d0/d3 $1000=$1234 d0=$1234
$1002=$5678 d1=$5678
MOVEM.L d0-d7/a0-a6,-(a7) will push all registers onto the stack.
MOVEM.L (a7)+,d0-d7/a0-a6 will pull all registers from the stack.
Instruction: MOVEP
Syntax: MOVEP Dn,w(An) or MOVEP w(An),Dn
Data sizes: Word, Long
Condition codes affected: None
Function: Transfer data from or to a peripheral. This instruction
has been specially designed for communication with all
devices which have been originally designed for 8-bit
micro-processors. This way the 68000 can communicate
with these devices. E.g. in the Atari are two ACIA's
present. ACIA's are designed for 8-bit computers. I
won't explain the operation of this instruction here
for it is rather seldom used, especially by beginners.
If you want to know all about this instruction I
suggest you contact the writer of this article.
Instruction: MOVEQ
Syntax: MOVEQ #,Dn
Data sizes: Long
Condition codes affected: See move.
Function: This instruction provides an efficient way (both in
space and time) to set a data register to a value).
Values range from -128 to +127 decimal. Most assemblers
will generate MOVEQ-instructions where possible.
Example:
Instruction Before After
MOVEQ #$34,d0 d0=ffffffff d0=00000034
Instruction: PEA
Syntax: PEA <ea>
Data sizes: Long
Condition codes affected: None
Addressing modes:
source: (An)
w(An)
b(An,Rn)
w
l
w(PC)
b(PC,Rn)
Function: Push an address onto the stack. This instruction is
often used to write position independent code. It has
nearly the same function as MOVE.L <ea>,-(a7).
Example:
Instruction Before After
PEA (a6) a6=12345678 a6=12345678
a7=44444444 a7=44444448
Instruction: SWAP
Syntax: SWAP Dn
Data sizes: None
Condition codes affected: V, C: always cleared
Z set if the result is 0
N set if bit 31 of the result is 1
Function: exchange upper and lower half of a data register. This
instruction is often used in conjunction with the
divide operation (will be explained further)
Example:
Instruction Before After
SWAP d0 d0=12345678 d0=56781234
Next time I will discuss the integer arithmetic operations. By
the way: I'm beginning to believe that this course is the best
there is, since I don't get any comments!!! If you read this and
react you can earn yourself a surprise.
Disclaimer
The text of the articles is identical to the originals like they appeared
in old ST NEWS issues. Please take into consideration that the author(s)
was (were) a lot younger and less responsible back then. So bad jokes,
bad English, youthful arrogance, insults, bravura, over-crediting and
tastelessness should be taken with at least a grain of salt. Any contact
and/or payment information, as well as deadlines/release dates of any
kind should be regarded as outdated. Due to the fact that these pages are
not actually contained in an Atari executable here, references to scroll
texts, featured demo screens and hidden articles may also be irrelevant.