Skip to main content

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.