Skip to main content

MC 68000 MACHINE LANGUAGE COURSE PART IV by Mark van den Boer

What a pity!!  You missed the mega-surprise of part 3.  Next time 
better luck! I am gonna take that holiday to Hawaii myself!

This time I will discuss the Integer Arithmetic Instructions. The 
syntax used is of course the same as in part 3,  so when in doubt 
refer  to  part  3.  This class of instructions  is  used  to  do 
mathematical  calculations.  This  group is very  often  used  by 
assembly  language programmers,  especially the instructions  for 
adding and subtracting.

Integer Arithmetic Instructions

Instruction:   ADD
Syntax:        ADD Dn,<ea>
               ADD <ea>,Dn
Data sizes:    byte, word, long

Condition codes affected:
               X, C set by carry out of the most significant bit
               N    set if the result was negative, cleared otherwise
               Z    set if the result was zero, cleared otherwise
               V    set if the result overflowed, cleared otherwise
Addressing modes:
Source: (destination is Dn)
          Dn
          An
          (An)
          (An)+
          -(An)
          w(An)
          b(An,Rn)
          w
          l
          w(PC)
          b(PC,Rn)

Destination:
          Dn
          (An)
          (An)+
          -(An)
          w(An)
          b(An,Rn)
          w
          l
Function: Add  source  to  destination  and  put  the  result  in 
          destination.
Examples:
Instruction              Before         After
ADD.W d0,d1              d0=00000011    d0=00000011
                         d1=0000FFFA    d1=0000000B
                         XNZVC=00000    XNZVC=11001
ADD.L (a0),d0            d0=00000022    d0=00000027
                         a0=12345678    a0=12345678
                    12345678 contains 5
                         XNZVC=00000    XNZVC=00000

Instruction:   ADDA
Syntax:        ADDA <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)
          #
Destination:
          An

Function: Add a value to an address register. This operation does 
          not change any of the condition code values.  Note that 
          most  operations  that have an address  register  as  a 
          destination does not change the condition codes.
Example:
Instruction              Before         After
ADDA.L a0,a0             a0=00000002    a0=00000004
Notice  that this instruction has the same effect as  multiplying 
the address register with two (if this was possible).

Instruction:   ADDI
Syntax:        ADDI #,<ea>
This instruction has exactly the same characteristics as the  ADD 
instruction, except that the source can only be a constant.

Instruction:   ADDQ
Syntax:        ADDQ #,<ea>
Same story as for ADDI,  except that the immediate values in  the 
source  field  can only range from 1 to 8.  Q stands  for  Quick, 
since this instruction is the fastest way to add a number from  1 
to 8 to a destination operand.
A note on ADD, ADDI, ADDQ:
Most assemblers accept the following instruction: ADD #1,Dn
and will translate it automatically to ADDQ #1,Dn    thus  saving 
a few bytes of object code and some clock cycles execution time.

Instruction:   ADDX
Syntax:        ADDX Dn,Dn
               ADDX -(An),-(An)
Data sizes:    byte, word, long
Condition codes affected: see ADD
Function: Add  X-bit  and  source to destination  and  store  the 
          result  in destination.  This instruction is  used  for 
          multiple  precision  operations and is  therefore  only 
          available with the two addressing modes mentioned.
Example:
Instruction              Before         After
ADDX.B -(a0),-(a1)       a0=10001001    a0=10001000
                         a1=10002001    a1=10002000
                 10001000 contains AA   the same
                 10002000 contains 5A   10002000 contains 4
                         X=0            X=1
ADDX.B -(a0),-(a1)        a0=10001000    a0=10000fff
                         a1=10002000    a1-10001fff
                 10000fff contains 0    the same
                 10001fff contains 0    10001fff contains 1
                         X=1            X=0
In this example the word that begins at 10000fff is added to  the 
word that begins at 10001fff.  If one should try to do this  with 
two  ADD.W instruction an address error would occur  since  words 
always must be aligned to even addresses. This instruction can be 
compared to the ADC instruction of the 6502 and 6809.

Instruction:   CLR
Syntax:        CLR <ea>
Data sizes:    byte, word, long
Condition codes affected:
               N    always cleared
               Z    always set
               V    always cleared
               C    always cleared

Addressing modes:
          Dn
          (An)
          (An)+
          -(An)
          w(An)
          b(An,Rn)
          w
          l
Function: Set an effective address to zero. You will have noticed 
          that you can't CLR an address register.  However,  most 
          assemblers  allow  the  programmer to  CLR  an  address 
          register  by  substituting CLR a0 with SUB.L  a0,a0   . 
          This instruction has exactly the same result.
Example:
Instruction              Before         After
CLR.W d0                 d0=ffffffff    d0=00000000
                         NZVC=1011      NZVC=0100

Instruction:   CMP
Syntax:        CMP <ea>,Dn
Data sizes:    byte, word, long
Condition codes affected: NZVC (X is not affected)
Addressing modes (source):
          Dn
          An
          (An)
          (An)+
          -(An)
          w(An)
          b(An,Rn)
          w
          l
          w(PC)
          b(PC,Rn)
Function: compare an effective address with a data  register.  In 
          fact  all  condition codes are set as  if  Dn-<ea>  was 
          performed.  So CMP is kind of a subtraction which  only 
          affects the conditon codes.

Example:
Instruction              Before         After
CMP.L d0,d1              d0=00000001    d0=00000001
                         d1=00000002    d1=00000002
                         NZVC=1111      NZVC=0000

Instruction:   CMPA
Syntax:        CMPA <ea>,An
Data sizes:    word, long
Function: This  instruction  differs only from CMP  in  that  the 
          second  operand  is an address register and  that  byte 
          isn't allowed as a data size.

Instruction:   CMPI
Syntax:        CMPI #,Dn
Function: Yes,  it is nearly exactly the same as compare but  now 
          the first operand must be a constant.

Instruction:   CMPM
Syntax:        CMPM (An)+,(An)+
Function: Again, nearly exactly the same as CMP, but now both the 
          source  and  destination operand must  be  (An)+.  This 
          instruction  is used to compare areas  of  memory.  For 
          those of you who have a working knowledge of C:  strcmp 
          can be programmed easy with this instruction.

Note on all CMPx instructions.
Most assemblers accept instructions like:
CMP.W (a0)+,(a1)+
CMP.L #3,d0
Substitution of CMPM,  CMPI and CMPA are automatically  performed 
by the assembler.

Instruction:   DIVS
Syntax:        DIVS <ea>,Dn
Data sizes:    word

Condition codes affected:
               N    behaves normal; undefined on overflow
               Z    behaves normal; undefined on overflow
               V    behaves normal
               C    always cleared
Addressing modes (source):
          Dn
          (An)
          (An)+
          -(An)
          w(An)
          b(An,Rn)
          w
          l
          w(PC)
          b(PC,Rn)
          #

Function: Guess  what?   This  instruction  performs  a  division 
          between two signed numbers. The 
          destination  register  is  always a  longword  and  the 
          source operand is always a word. After the division the 
          destination operand contains the result.  The  quotient 
          is always in the lower word and the remainder is always 
          in the high order word of the data register! This way a 
          modulo operation is also performed,  you just SWAP  the 
          data  register  and you have your result in  the  lower 
          word  of the data register.  Overflow occurs  when  you 
          attempt to divide a large number by a small number e.g. 
          ffffff divided by 1,  the result doesn't fit in a word. 
          Another error occurs when attempting to divide by zero. 
          In this case the 68000 generates an exception and  will 
          trap  to  a special routine which handles  division  by 
          zero erros.  On the Atari you must set up this  routine 
          yourself.  E.g.  FLOYD  (a  machine  language  monitor) 
          responds  to  a  division by zero  with  the  following 
          sentence "The answer is 42". Remember, don't panic when 
          you see such an answer.

Example:
Instruction              Before         After
DIVS #3,d0               d0=0000000B    d0=00020003
                         NZVC=1111      NZVC=0000

Instruction: DIVU
Function: Nearly  exactly the same as DIVS,  only this time  both 
          operands are assumed to be unsigned.

Instruction:   EXT
Syntax:        EXT Dn
Data sizes:    word, long
Condition codes affected:
               N    behaves normal
               Z    behaves normal
               V    always cleared
               C    always cleared

Function: turn  a byte into a word,  or turn a word into a  long. 
          This  instruction provides a convenient way to  turn  a 
          word into a long and still have the same value for that 
          register. If the high order bit of the data register is 
          0,  so the data register is positive, zeroes are padded 
          in, otherwise ones are padded in.
Example:
Instruction              Before         After
EXT.W d0                 d0=000000ff    d0=0000ffff
EXT.L d0                 d0=ffff0000    d0=00000000

Instruction:   MULS
Syntax:        MULS <ea>,Dn
Data sizes:    word
Condition codes affected:
               N    behaves normal
               Z    behaves normal
               V    always cleared
               C    always cleared

Addressing modes (source):
          Dn
          (An)
          (An)+
          -(An)
          w(An)
          b(An,Rn)
          w
          l
          w(PC)
          b(PC,Rn)
          #
Function: Ah!  another very handy instruction.  This  instruction 
          performs a multiplication of the source and destination 
          operand, putting the result in the destination operand.
Example:
Instruction              Before         After
MULS #3,d0               d0=0000000B    d0=00000021
                         NZVC=1111      NZVC=0000

Instruction: MULU
Function: Nearly  exactly the same as MULUS,  only this time  both 
          operands are assumed to be unsigned.

Instruction:   NEG
Syntax:        NEG <ea>
Data sizes:    byte, word, long
Condition codes affected: XNZVC (all behave normal)
Addressing modes:
          Dn
          (An)
          (An)+
          -(An)
          w(An)
          b(An,Rn)
          w
          l
Function: negate  an effective address operand.  In a high  level 
          language it would look like this: a = -a

Example:
Instruction              Before         After
NEG.L d0                 d0=00000001    d0=ffffffff

Instruction:   NEGX
Syntax:        NEGX <ea>
Data sizes:    byte, word, long
Condition codes affected: XNZVC (all behave normal)
Addressing modes:
          Dn
          (An)
          (An)+
          -(An)
          w(An)
          b(An,Rn)
          w
          l
Function: negate  an effective address operand and add the  X-bit 
          to  the  result.  This  is  another  instruction  which 
          provides a way to handle multi-precision  (e.g.  8-byte 
          integers).
Example:
Instruction              Before         After
NEGX.L d0                d0=00000001    d0=00000000
                         X=1            X=1

Instructions: SUB, SUBA, SUBI, SUBQ, SUBX
All these instruction perform subtractions.  They only differ  in 
that   way   from   from  the   ADD   instructions,   all   other 
characteristics are the same.

Instruction:   TAS
Syntax:        TAS <ea>
Data sizes:    byte
Condition codes affected:
               N    evaluated before setting the byte
               Z    evaluated before setting the byte
               V    always cleared
               C    always cleared

Addressing modes:
          Dn
          (An)
          (An)+
          -(An)
          w(An)
          b(An,Rn)
          w
          l
Function: First  test  the operand and set the  condition  codes, 
          then set the high-order bit to 1.  People who know what 
          semaphores (in programming of course...) are, immedia
          tely  will love this instruction.  For those who  don't 
          know what semaphores are: M. Ben Ari has written a good 
          book  on the subject called "Principles  of  Concurrent 
          Programming".  Never,  I repeat never,  read a book  on 
          this subject written by a certain Ir.  E.H.H.  Dijkstra 
          (not the famous Dijkstra,  this Dijkstra will never  be 
          famous).

Example:
Instruction              Before         After
TAS $436                 $436=00        $436=80
                         NZVC=1111      NZVC=0100
TAS $436                 $436=FF        $436=FF
                         NZVC=1111      NZVC=1000

Instruction:   TST
Syntax:        TST <ea>
Data sizes:    byte, word, long
Condition codes affected:
               N    behaves normal
               Z    behaves normal
               V    always cleared
               C    always cleared

Addressing modes:
          Dn
          (An)
          (An)+
          -(An)
          w(An)
          b(An,Rn)
          w
          l
Function: test an effective address operand. This instruction can 
          be  seen as CMP <ea>,d0 where d0 is 0.  TST  is  nearly 
          always followed by a branch instruction (more on  these 
          later)

To  the people who also read the last lines (I hope  you've  also 
read most of the preceeding ones):  Phone me and tell me how  you 
like this course.

My phonenumber (in Holland) is:
Weekends: 013-422397
Midweek:  070-933487 (only at evenings)

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.