Skip to main content
© Chaos

68000 ASSEMBLY LANGUAGE COURSE PART II by Mark van den Boer

Welcome to part II of this course.  In part I,  some fundamentals 
of  the 68000 were shown.  In this part,  I will show  you  which 
addressing modes the 68000 uses.  First an example of  addressing 
modes which the 6502 and 6809 use:

lda #10   * immediate addressing
lda $10   * zero-page (6502) or direct-page addressing (6809)
inx       * inherent (6502)
inca      * inherent (6809)

Now, what does a line of code in 68000 assembler look like?

LABEL   OPCODE  OPER1,OPER2      COMMENT

The meanings of these fields are:
label:   A  name  given to this line  of  code.  Some  assemblers 
         require  a :  to follow the label-name.  This  field  is 
         optional.

opcode:  This field specifies the operation you wish to  perform. 
         It is the only field that isn't optional.  Depending  on 
         the opcode the 68000 expects 0, 1 or 2 operands.
oper1:   The  first  operand  to  appear  with  the  opcode.  The 
         appearance  of  this  field  depends  on  the  specified 
         opcode.
oper2:   The  second  operand  to appear  with  the  opcode.  The 
         appearance of this field depends (surprise, surprise) on 
         the specified opcode.
comment: Another optional field which is used for commenting  all 
         tricks  people put in their  programs.  Most  assemblers 
         require a * as the first character of the comment field. 
         The comment field is optional.

Now what does an addressing mode do? An addressing mode specifies 
on which data the opcode (instruction) must operate.
The  68000 has a total of 14 addressing modes,  all of which  now 
will  explained.  As examples in all addressing modes I will  use 
the MOVE instruction. MOVE can have the .b, .w and .l suffixes as 
mentioned in part I of the course. The MOVE instruction moves the 
data  specified  by oper1 to the place specified  by  oper2.  For 

example:  MOVE.B $1,$2 performs exactly the same operation as the 
following 6502 and 6809 code: LDA $1    STA $2.

The addressing modes:

1. Inherent addressing

In  this  addressing mode there are no operands  since  they  are 
already supplied by the opcode.
E.g.: RESET    * reset all peripherals
RESET  is  an 68000 instruction which is used to  reset  all  the 
peripherals.

2. DATA REGISTER DIRECT ADDRESSING

Assembler syntax: Dn (n can range from 0 to 7)
In this addressing mode a data register contains the operand.
E.g.:

Instruction          Before             After
MOVE.B D1,D0      d0=ffffffff         d0=ffffff67
                  d1=01234567         d1=01234567
MOVE.W D1,D0      d0=ffffffff         d0=ffff4567
                  d1=01234567         d1=01234567
MOVE.L D1,D0      d0=ffffffff         d0=01234567
                  d1=01234567         d1=01234567

As  you might have noticed,  an instruction with .b as  a  suffix 
only  changes  the  lowest  8  bits  of  the   destination,   and 
instructions  with .w as a suffix only change the lowest 16  bits 
of the destination.  Instructions with .l as a suffix change  all 
32 bits of the destination.

3. ADDRESS REGISTER DIRECT ADDRESSING

Assembler syntax: An (n can range from 0 to 7)
In this addressing mode an address register contains the operand. 
Byte  operators  (those with .b suffix) are not allowed  in  this 
addressing mode. When using the address register as a destination 
and  it  is a word operation (suffix is .w),  the word  is  sign-
extended into a longword.  This means that during a  wordtransfer 
into a data register the upper 16 bits are filled with the  value 
of  the  most-significant bit (this is bit 15) of  the  word.  An 
example below will show you how it's done.
E.g.:

Instruction          Before             After
MOVE.W A1,D0       d0=ffffffff        d0=ffff4567
                   a1=01234567        a1=01234567
MOVE.W D0,A1       d0=01234567        d0=01234567
                   a1=ffffffff        a1=00004567  <- extend!!
MOVE.W D0,A1       d0=0000ffff        d0=0000ffff
                   a1=00000000        a1=ffffffff  <- extend!!
MOVE.L A1,D0       d0=ffffffff        d0=01234567
                   a1=01234567        a1=01234567

4. ADDRESS REGISTER INDIRECT ADDRESSING

Assembler syntax: (An)   (n between 0 and 7)
In  this  addressing  mode,  the address  register  contains  the 
address of the operand.  In assembler this is being denotated  by 
putting parentheses around an address registers name,  e.g. (a0). 
The contents of a0 points to the address where the data has to be 
fetched from. When using word (.w) or longword (.l) addressing it 
is  absolutely  necessary that the address register  contains  an 
even number (I will explain the reason for this in a  forthcoming 
article).
E.g.:

Instruction          Before             After
MOVE.L (A1),D0    d0=ffffffff        d0=01234567
                  a1=00001000        a1=00001000
            address $1000 contains 01234567
MOVE.L D0,(A1)    d0=76543210        d0=76543210
                  a1=00001000        a1=00001000
            address $1000 now contains 76543210

5. ADDRESS REGISTER INDIRECT ADDRESSING WITH POST-INCREMENT

Assembler syntax: (An)+     (n between 0 and 7)
This  addressing  mode resembles the  address  register  indirect 
addressing mode. The only difference is that after having fetched 
or  stored the data,  the address register  is  incremented.  The 
increment depends on the suffix used in the opcode. If the suffix 
is  .b then the address register will be incremented by  one.  If 
the suffix is .w then the address register will be incremented by 
two (one word is two bytes). If the suffix is .l then the address 
register  will  be  incremented by four  (one  longword  is  four 
bytes). In assembler this addressing mode is denotated by putting 
the address register within parentheses followed by a + sign. For 
example: (a7)+
E.g.:

Instruction          Before             After
MOVE.L (A1)+,D0   d0=ffffffff        d0=01234567
                  a1=00001000        a1=00001004
            address $1000 contains 01234567
MOVE.W (A1)+,D0   d0=ffffffff        d0=ffff0123
                  a1=00001000        a1=00001002
            address $1000 contains 01234567
MOVE.B (A1)+,D0   d0=ffffffff        d0=ffffff01
                  a1=00001000        a1=00001001
            address $1000 contains 01234567
MOVE.L D0,(A1)+   d0=76543210        d0=76543210
                  a1=00001000        a1=00001004
            address $1000 now contains 76543210

6. ADDRESS REGISTER INDIRECT ADDRESSING WITH PRE-DECREMENT

Assembler syntax: -(An)     (n between 0 and 7)
This  addressing  mode resembles the  address  register  indirect 
addressing  mode.  The  only  difference  is  that  after  before 
fetching  or  storing the data,  the address register  is  decre
mented.  The decrement depends on the suffix used in the  opcode. 
If the suffix is .b then the address register will be decremented 
by  one.  If the suffix is .w then the address register  will  be 
decremented by two (one word is two bytes).  If the suffix is  .l 
then  the  address  register will be  decremented  by  four  (one 
longword  is four bytes).  In assembler this addressing  mode  is 
denotated  by  putting the address  register  within  parentheses 
preceded by a - sign. For example: -(a7)
E.g.:

Instruction          Before             After
MOVE.L -(A1),D0   d0=ffffffff        d0=01234567
                  a1=00001004        a1=00001000
            address $1000 contains 01234567
MOVE.W -(A1),D0   d0=ffffffff        d0=ffff4567
                  a1=00001004        a1=00001002
            address $1000 contains 01234567
MOVE.B -(A1),D0   d0=ffffffff        d0=ffffff67
                  a1=00001004        a1=00001003
            address $1000 contains 01234567
MOVE.L D0,-(A1)   d0=76543210        d0=76543210
                  a1=00001004        a1=00001000
            address $1000 now contains 76543210

7. ADDRESS REGISTER INDIRECT ADDRESSING WITH DISPLACEMENT

Assembler syntax: w(An)    (w stands for word displacement)
This  addressing  is  also rather  similar  to  address  register 
indirect  addressing.  The only difference lies in the fact  that 
before  fetching or moving the data a 16-bit signed  displacement 
is  added  to the contents of the address register  (the  address 
register  itself does not change).  In assembler this  addressing 
mode  is  denotated  by enclosing the address  register  name  in 
parentheses  preceded by a 16-bit constant.  For  example:  8(a6) 
denotes  the memory location whose address is the contents of  a6 
plus 8.  This addressing method comes in very handy when  passing 
parameters to subroutines.
By the way, did you ever wonder why the ATARI ST has a resolution 
of  640  by  400  pixels?
Here's one reason:  640*400=256000 bits=32000 bytes.  Since 32000 
bytes  can  be  addressed using 16  bits,  the  address  register 
indirect with displacement is an easy way to address the screen.
E.g.:

Instruction          Before             After
MOVE.L 8(A1),D0   d0=ffffffff        d0=01234567
                  a1=00001000        a1=00001000
            address $1008 contains 01234567
MOVE.L D0,-6(A1)  d0=76543210        d0=76543210
                  a1=00001006        a1=00001006
            address $1000 now contains 76543210

8. ADDRESS REGISTER INDIRECT ADDRESSING WITH INDEX

Assembler syntax: b(An,Rn.w) or b(An,Rn.l)
(  b  stands for byte,  w and l for word and longword and  R  for 
register).
This  addressing mode makes it possible to add a  variable  index 
(contained in an address or data register) to an address register 
and  also an eight bit signed displacement.   The variable  index 
may be either word or longword.  Both the index and  displacement 
are sign extended before they are added to the address register.
E.g.:

Instruction            Before             After
MOVE.L 8(A1,A0.L),D0   d0=ffffffff        d0=01234567
                       a1=00001000        a1=00001000
                       a0=00078000        a0=00078000
                   address $79008 contains 01234567
MOVE.L 8(A1,A0.W),D0   d0=ffffffff        d0=01234567
                       a1=00001000        a1=00001000
                       a0=00078000        a0=00078000
*** a0.w=8000 -> sign-extend gives ffff8000 ***
                   address $ffff8008 contains 01234567
MOVE.W 8(A1,D0.L),D0   d0=0001fffe        d0=00010123
                       a1=00001000        a1=00001000
*** 00001000 (contents of a1)
    0001fffe (contents of d0.l)
    00000008 (sign-extended byte displacement)
    ---------
    00021006
                   address $21006 contains 01234567
MOVE.L 8(A1,D0.W),D0   d0=0001fffe        d0=01234567
                       a1=00001000        a1=00001000
*** 00001000 (contents of a1)
    fffffffe (sign-extended contents of d0.w)
    00000008 (sign-extended byte displacement)
    ---------
    00001006
                   address $1006 contains 01234567

9. ABSOLUTE SHORT ADDRESSING

Assembler syntax: x  (x is a 16 bit constant)
With  absolute short addressing it is only possible to specify  a 
16  bit constant.  At execution time the 68000 sign  extends  the 
word into a long address,  meaning that only addresses 0 to  7fff 
and ffff8000 to ffffffff can be addressed using this  form.  This 
addressing mode can be compared with zero-page addressing on  the 
6502 and direct-page addressing on the 6809.Like on the 6502  and 
6809  this mode is faster than any other  mode.  This  addressing 
mode  can be compared with zero-page addressing on the  6502  and 
direct-page addressing on the 6809.
By the way, on the Atari ST, the lower 32 K of memory can only be 
accessed in supervisor-mode (the S-bit in SR is set, see part I).
E.g.:

Instruction            Before             After
MOVE.L $1234,D0      d0=ffffffff       d0=01234567
                    address 1234 contains 01234567
                   ( the $ sign is used to denote a hex digit)
MOVE.L $8000,D0      d0=ffffffff       d0=76543210
                    address $ffff8000 contains 76543210

10. ABSOLUTE LONG ADDRESSING

Assembler syntax: l   (l is 32 bit constant)
With this addressing mode a long address is supplied.  It is very 
similar to absolute short addressing.
E.g.:
Instruction              Before             After
MOVE.L $12345678,D0   d0=ffffffff         d0=01234567
                      address $00345678 contains 01234567
Note  that since the address bus is only 24 bits wide  the  upper 
byte of the address is ignored by the 68000.

11. PROGRAM COUNTER WITH DISPLACEMENT

Assembler syntax: x(PC)    (x is a 16 bit constant)
This  addressing  mode is in fact the same  as  address  register 
indirect  with  displacement.  The only difference  is  that  the 
address register is replaced with the PC (the PC is in fact  also 
an address register).
E.g.:

Instruction          Before             After
MOVE.L 8(PC),D0   d0=ffffffff        d0=01234567
                  pc=00001000        pc=00001000
            address $1008 contains 01234567

12. PROGRAM COUNTER WITH INDEX

Assembler syntax: b(PC,Rn.L) or b(PC,Rn.w)   (b is 8 bits)
This  mode  is  in  fact  the  same  address  register   indirect 
addressing with index.
E.g.:

Instruction            Before             After
MOVE.L 8(PC,A0.L),D0   d0=ffffffff        d0=01234567
                       pc=00001000        pc=00001000
                       a0=00078000        a0=00078000
                   address $79008 contains 01234567
MOVE.L 8(PC,A0.W),D0   d0=ffffffff        d0=01234567
                       pc=00001000        pc=00001000
                       a0=00078000        a0=00078000
*** a0.w=8000 -> sign-extend gives ffff8000 ***
                   address $ffff8008 contains 01234567
MOVE.W 8(PC,D0.L),D0   d0=0001fffe        d0=00010123
                       pc=00001000        pc=00001000
*** 00001000 (contents of pc)
    0001fffe (contents of d0.l)
    00000008 (sign-extended byte displacement)
    ---------
    00021006
                   address $21006 contains 01234567
MOVE.L 8(PC,D0.W),D0   d0=0001fffe        d0=01234567
                       pc=00001000        pc=00001000
*** 00001000 (contents of pc)
    fffffffe (sign-extended contents of d0.w)
    00000008 (sign-extended byte displacement)
    ---------
    00001006
                   address $1006 contains 01234567

13. IMMEDIATE ADDRESSING

Assembler syntax: #x   (x is byte, word or longword)
The  data for the operation is the value x.  Programmers  of  the 
6502  and 6809 will recognize this addressing mode.  For  example 
(6502 and 6809) LDA #$21.
E.g.:

Instruction               Before             After
MOVE.L #$A03B4C11,D0    d0=00000000       d0=a03b4c11

14. STATUS REGISTER ADDRESSING

Assembler syntax: SR or CCR
This mode is used to control the contents of this  register.  See 
part  I  of this course for the individual meanings of  the  bits 
contained  in this register.  Changes to the SR can only be  made 
when in user-mode. Changes to the CCR can be made in any mode.
E.g.:

Instruction            Before             After
MOVE.W SR,D0        d0=87654321        d0=87652700
                    sr=2700            sr=2700
MOVE.W #$0500,SR    sr=2700            sr=0500
Notice that the 68000 was in supervisor mode before executing the 
instruction  but  after  completion it is  in  user  mode!!  This 
operation isn't possible the other way around.
To  conclude  this  part,  I  will give  you  a  summary  of  the 
addressing modes of the 68000.

SYNTAX          NAME
-----------------------------------
Dn          | Data register direct
An          | Address register direct
(An)        | Address register indirect
(An)+       | Address register indirect with post-increment
-(An)       | Address register indirect with pre-decrement
w(An)       | Address register with displacement
b(An,Rn)    | Address register with index
w           | Absolute short
l           | Absolute long
w(PC)       | PC with displacement
b(PC,Rn)    | PC with index
#x          | Immediate
SR or CCR   | Status register

b is a byte constant
w is a word constant
l is a long constant
x any of b, l or w
n is a register number ranging from 0 to 7
R is a register specifier, either A or D

If you have any comments on these courses, please let me know!

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.