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.