
       ASSEMBLY LANGUAGE COURSE PART VI by Mark van den Boer



Shift and Rotate Operations



Instruction:   ASL

Syntax:        ASL #,Dn (the immediate operand always modulo 8)

               ASL Dn,Dn (the first operand always modulo 8)

               ASL <ea>

Data sizes:    byte,  word,  long  except for ASL <ea> which  only

               allows word and long as data sizes.

Condition codes affected:

               X    set to the last bit shifted out

               N    set to the most significant bit of the result

               Z    set if the result is zero, cleared otherwise

               V    set  if  the most significant bit  is  changed

                    during the operation

               C    see the X-bit











Addressing modes allowed with the ASL <ea> instruction:

Destination:

          (An)

          (An)+

          -(An)

          w(An)

          b(An,Rn)

          w

          l

Function: Perform  a shift left of the destination  operand.  This

          instruction can be used as a fast form of multiplying an

          operand  with a power of two.  On a processor  like  the

          6502  this  instruction  is the only way  to  perform  a

          multiply operation.  The lower bit of the destination is

          always set to zero.

Examples:

Instruction              Before         After

ASL.L d0,d1              d0=33333333    d0=33333333

                         d1=00000005    d1=00000028

ASL.W $4ee               $4ee=0009      $4ee=0012





Instruction:   ASR

Syntax:        ASR #,Dn (the immediate operand always modulo 8)

               ASR Dn,Dn (the first operand always modulo 8)

               ASR <ea>

Data sizes:    byte,  word,  long  except for ASR <ea> which  only

               allows word and long as data sizes.

Condition codes affected:

               X    set to the last bit shifted out

               N    set to the most significant bit of the result

               Z    set if the result is zero, cleared otherwise

               V    set  if  the most significant bit  is  changed

                    during the operation

               C    see the X-bit

Addressing modes allowed with the ASR <ea> instruction:

Destination:

          (An)

          (An)+

          -(An)

          w(An)

          b(An,Rn)

          w

          l

Function: Perform a shift right of the destination  operand.  This

          instruction  can be used as a fast form of  dividing  an

          operand  with a power of two.  On a processor  like  the

          6502  this  instruction  is the only way  to  perform  a

          divide  operation.  The upper bit (sign bit)  is  always

          repeated.

Examples:

Instruction              Before         After

ASR.L d0,d1              d0=33333333    d0=33333333

                         d1=00000005    d1=00000002

ASR.W $4ee               $4ee=8009      $4ee=c004





Instruction:   LSL

See the ASL instruction.  The LSL instruction is exactly the same.

At the moment I haven't got the machine codes for the ASL and LSL

operations  but I think that even the machine codes are the  same.

E.g.  on the 6809 both ASL and LSL exist but translate to the same

machine code.







Instruction:   LSR

Syntax:        LSR #,Dn (the immediate operand always modulo 8)

               LSR Dn,Dn (the first operand always modulo 8)

               LSR <ea>

Data sizes:    byte,  word,  long  except for LSR <ea> which  only

               allows word and long as data sizes.

Condition codes affected:

               X    set to the last bit shifted out

               N    set to the most significant bit of the result

               Z    set if the result is zero, cleared otherwise

               V    set  if  the most significant bit  is  changed

                    during the operation

               C    see the X-bit

Addressing modes allowed with the LSR <ea> instruction:

Destination:

          (An)

          (An)+

          -(An)

          w(An)

          b(An,Rn)

          w

          l

Function: Perform a shift right of the destination  operand.  This

          instruction differs from ASR in that the high order  bit

          is always cleared.

Examples:

Instruction              Before         After

LSR.L d0,d1              d0=33333333    d0=33333333

                         d1=00000005    d1=00000002

LSR.W $4ee               $4ee=0009      $4ee=0004





Instruction:   ROL

Syntax:        ROL #,Dn (the immediate operand always modulo 8)

               ROL Dn,Dn (the first operand always modulo 8)

               ROL <ea>

Data sizes:    byte, word, long

Condition codes affected:

               X    not affected

               N    set to the most significant bit of the result

               Z    set if the result is zero, cleared otherwise

               V    always cleared

               C    set to the last bit shifted out the operand



Addressing modes allowed with the ROL <ea> instruction:

Destination:

          (An)

          (An)+

          -(An)

          w(An)

          b(An,Rn)

          w

          l

Function: Perform  a  bitwise  rotate  left  of  the   destination

          operand.

Examples:

Instruction              Before         After

ROL.L d0,d1              d0=00000001    d0=00000001

                         d1=88000001    d1=10000002  (C bit set)

ROL.W $4ee               $4ee=8009      $4ee=0012













Instruction:   ROR

Syntax:        ROR #,Dn (the immediate operand always modulo 8)

               ROR Dn,Dn (the first operand always modulo 8)

               ROR <ea>

Data sizes:    byte, word, long

Condition codes affected:

               X    not affected

               N    set to the most significant bit of the result

               Z    set if the result is zero, cleared otherwise

               V    always cleared

               C    set to the last bit shifted out the operand

Addressing modes allowed with the ROR <ea> instruction:

Destination:

          (An)

          (An)+

          -(An)

          w(An)

          b(An,Rn)

          w

          l

Function: Perform  a  bitwise  rotate  right  of  the  destination

          operand.

Examples:

Instruction              Before         After

ROR.L d0,d1              d0=00000001    d0=00000001

                         d1=88000001    d1=c4000000  (C bit set)

ROR.W $4ee               $4ee=8009      $4ee=c004





Instruction:   ROXL

Syntax:        ROXL #,Dn (the immediate operand always modulo 8)

               ROXL Dn,Dn (the first operand always modulo 8)

               ROXL <ea>

Data sizes:    byte, word, long

Condition codes affected:

               X    set to the last bit shifted out the operand

               N    set to the most significant bit of the result

               Z    set if the result is zero, cleared otherwise

               V    always cleared

               C    set to the last bit shifted out the operand









Addressing modes allowed with the ROXL <ea> instruction:

Destination:

          (An)

          (An)+

          -(An)

          w(An)

          b(An,Rn)

          w

          l

Function: Perform  a  bitwise  rotate  left  of  the   destination

          operand.  There  is very little difference with the  ROL

          instruction.  By  the way,  it is very handy to  have  a

          wordprocessor    with   cut/paste    and    find/replace

          facilities.  All  I  did was cut out  the  complete  ROL

          instruction and replaced all ROL's by ROXL's.

Examples:

Instruction              Before         After

ROXL.L d0,d1             d0=00000001    d0=00000001

                         d1=88000001    d1=10000002

ROXL.W $4ee              $4ee=8009      $4ee=0012





Instruction:   ROXR

Syntax:        ROXR #,Dn (the immediate operand always modulo 8)

               ROXR Dn,Dn (the first operand always modulo 8)

               ROXR <ea>

Data sizes:    byte, word, long

Condition codes affected:

               X    set to the last bit shifted out the operand

               N    set to the most significant bit of the result

               Z    set if the result is zero, cleared otherwise

               V    always cleared

               C    set to the last bit shifted out the operand

Addressing modes allowed with the ROXR <ea> instruction:

Destination:

          (An)

          (An)+

          -(An)

          w(An)

          b(An,Rn)

          w

          l





Function: Perform  a  bitwise  rotate  right  of  the  destination

          operand.  There  is very little difference with the  ROR

          instruction.  By  the way,  it is very handy to  have  a

          wordprocessor    with   cut/paste    and    find/replace

          facilities.  All  I  did was cut out the  complete  ROXL

          instruction and replaced all ROXL's by ROXR's.

Examples:

Instruction              Before         After

ROXR.L d0,d1             d0=00000001    d0=00000001

                         d1=88000001    d1=10000002

ROXR.W $4ee              $4ee=8009      $4ee=0012







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



I would like to dedicate this part to Willeke,  who gives  Richard 

sleepless  nights and the inspiration to write even more  exciting 

issues of ST NEWS.  I only saw Willeke on photograph, but she must 

be  a fine girl.  In my opinion there are three qualities which  a 

girl  must have,  to qualify as a fine girl.  These are:  1)  like 

Queensrche,  2) like ST NEWS (no,  she doesn't have to like  this 

particular machine language course).

Now,  you're all anxious to know the third quality, aren't you? If 

you think you know the third one,  send your answer to ST NEWS.  A 

bottle  of  wine will be raffled among the persons  who  gave  the 

right answer.  There will be another bottle for the most  original 

answer!



Bit Manipulation instructions



Instruction:   BTST

Syntax:        BTST Dn,<ea> or BTST #,<ea>

Data sizes:    only byte when <ea> is an address.  Only long  when 

               <ea> is a data register.



Condition codes affected:

               X    not affected

               N    not affected

               Z    set if the result is zero, cleared otherwise

               V    not affected

               C    not affected

Addressing modes allowed:

Destination:

          Dn

          (An)

          (An)+

          -(An)

          w(An)

          b(An,Rn)

          w

          l

          w(PC)

          b(PC,Rn)

          #         (only when source is Dn)







Function: Test a single bit of an effective address operand.  Bits 

          are  numbered  from  0  to 31,  where  0  is  the  least 

          significant bit (you could use this instruction to  test 

          if  a number is odd).  This instruction is  useful  when 

          specific  bits of an operand have to  be  checked.  E.g. 

          when reading joystick information one could test with  a 

          single  instruction whether the fire-button was  pressed 

          or not.  Compared to the 6502 and 6809 this  instruction 

          (in  fact all bit manipulation instructions) are a  step 

          forward,  since  with these older processors one had  to 

          put  the data in a register first,  then filter the  bit 

          with  an AND-operation and then the Z-bit in the  status 

          register  was at last set.  Viva el 68000!!  Since  this 

          instruction has the rather odd property of only  working 

          on  byte  and  long operands it is  important  that  you 

          remember   what  I  wrote  in  a  previous  part   about 

          specifying data sizes.











Examples:

Instruction              Before              After

BTST.B #5,$345678        $345678             $345678 contains

                         contains $78        $78

                                             Z-bit is 1

BTST.L d0,d1             d0=0                d0=0

                         d1=$12345678        d1=$12345678

                                             Z-bit is 0





Instruction:   BCLR

Syntax:        BTST Dn,<ea> or BTST #,<ea>

Data sizes:    only byte when <ea> is an address.  Only long  when 

               <ea> is a data register.

Condition codes affected:

               X    not affected

               N    not affected

               Z    set if the result is zero, cleared otherwise

               V    not affected

               C    not affected





Addressing modes allowed:

Destination:

          Dn

          (An)

          (An)+

          -(An)

          w(An)

          b(An,Rn)

          w

          l

          w(PC)

          b(PC,Rn)

          #         (only when source is Dn)

Function: Bit  test and CLeaR.  First tests the bit to be  cleared 

          and  sets  the  Z-bit  accordingly,   then  clears   the 

          specified bit.













Examples:

Instruction              Before              After

BCLR.B #5,$345678        $345678             $345678 contains

                         contains $78        $58

                                             Z-bit is 1

BCLR.L d0,d1             d0=0                d0=0

                         d1=$12345678        d1=$12345678

                                             Z-bit is 0





Instruction:   BSET

Syntax:        BSET Dn,<ea> or BSET #,<ea>

Data sizes:    only byte when <ea> is an address.  Only long  when 

               <ea> is a data register.

Condition codes affected:

               X    not affected

               N    not affected

               Z    set if the result is zero, cleared otherwise

               V    not affected

               C    not affected





Addressing modes allowed:

Destination:

          Dn

          (An)

          (An)+

          -(An)

          w(An)

          b(An,Rn)

          w

          l

          w(PC)

          b(PC,Rn)

          #         (only when source is Dn)

Function: Bit test and SET. First tests the bit to be set and sets 

          the Z-bit accordingly, then sets the specified bit. This 

          instruction  and  the BCLR instruction can  be  used  as 

          alternatives to the TAS-instruction.











Examples:

Instruction              Before              After

BSET.B #5,$345678        $345678             $345678 contains

                         contains $78        $78

                                             Z-bit is 1

BSET.L d0,d1             d0=0                d0=0

                         d1=$12345678        d1=$12345679

                                             Z-bit is 0





Instruction:   BCHG

Syntax:        BCHG Dn,<ea> or BCHG #,<ea>

Data sizes:    only byte when <ea> is an address.  Only long  when 

               <ea> is a data register.

Condition codes affected:

               X    not affected

               N    not affected

               Z    set if the result is zero, cleared otherwise

               V    not affected

               C    not affected





Addressing modes allowed:

Destination:

          Dn

          (An)

          (An)+

          -(An)

          w(An)

          b(An,Rn)

          w

          l

          w(PC)

          b(PC,Rn)

          #         (only when source is Dn)

Function: Bit test and CHanGe.  First tests the bit to be  changed 

          and  sets  the  Z-bit  accordingly,   then  changes  the 

          specified bit.













Examples:

Instruction              Before              After

BCHG.B #5,$345678        $345678             $345678 contains

                         contains $78        $58

                                             Z-bit is 1

BCHG.L d0,d1             d0=0                d0=0

                         d1=$12345678        d1=$12345679

                                             Z-bit is 0





Binary Coded Decimal (BCD) instructions



To understand this instructionclass we must first know what a BCD-

digit is.  It is a representation of decimal digits in an array of 

bytes  (array may be of length 1 or greater).  In every  byte  the 

decimal  number  0  to 99 can be  represented.  This  is  done  as 

follows:  a  byte can be divided into two four-bit  parts,  called 

nibbles.  In every nibble,  one decimal digit is represented. This 

implicates that the binary combination 1010 can never occur in BCD 

representation,  since it isn't in the decimal range from 0 to  9. 





The BCD-representation is especially convenient when printing such 

a digit, since it doesn't take much calculation to convert it to a 

printable character.  A disadvantage of the BCD-representation  is 

that one doesn't use the full storage capacity of a byte or word.

The 68000 has three special BCD-artithmetic instructions.





Instruction:   ABCD

Syntax:        ABCD Dn,Dn or ABCD -(An),-(An)

Data sizes:    byte

Condition codes affected:

               X    set by carry out of most significant

                    BCD-nibble, cleared otherwise

               N    undefined

               Z    set if the result is zero, cleared otherwise

               V    undefined

               C    same as X-bit

Function: Add two BCD-digits.  The predecremeting addressing  mode 

          has   been  provided  for  computations  with   multiple 

          precision  BCD-numbers.   This  implies  that  the  most 

          significant  BCD-numbers  must be stored  in  the  lower 

          memory addresses.

Examples:

Instruction              Before              After

ABCD.B d0,d1             d0=$53              d0=$53

                         d1=$32              d1=$85





Instruction:   SBCD

Syntax:        SBCD Dn,Dn or SBCD -(An),-(An)

Data sizes:    byte

Condition codes affected:

               X    set by carry out of most significant

                    BCD-nibble, cleared otherwise

               N    undefined

               Z    set if the result is zero, cleared otherwise

               V    undefined

               C    same as X-bit

Function: Subtract two BCD-digits.

Examples:

Instruction              Before              After

ABCD.B d0,d1             d0=$53              d0=$53

                         d1=$32              d1=$21



Instruction:   NBCD

Syntax:        NBCD <ea>

Data sizes:    byte

Addressing modes allowed:

          Dn

          (An)

          (An)+

          -(An)

          w(An)

          b(An,Rn)

          w

          l

Condition codes affected:

               X    set by borrow out of most significant

                    BCD-nibble, cleared otherwise

               N    undefined

               Z    set if the result is zero, cleared otherwise

               V    undefined

               C    same as X-bit







Function: Negate  a  BCD-number.  How  it functions  can  be  best 

          described with an example.  Let's negate $23.  The  NBCD 

          operation yields $77.  Now,  how did we get this result? 

          It's easy, just subtract $23 from $99 and you've got it. 

Examples:

Instruction              Before              After

NBCD.B d0                d0=$43              d0=$56





This  is  the end of part seven.  Next time I will deal  with  all 

program flow instruction, such as branches and jumps. 







MC 68000 ASSEMBLY LANGUAGE COURSE PART VIII by Mark van den Boer



Program Control Instructions



This  class of instructions enables a programmer to create  loops 

and  IF-THEN-ELSE  like  decisions.  That's  why  it's  the  most 

important group of instructions and every programmer should  have 

a  thorough knowledge of this group.  This class of  instructions 

are specifically meant to affect the program counter.



Instructions:  Bcc  (cc stands for Condition Code)

Syntax:        Bcc  <address>

Data sizes:    Byte  or word.  This implicates that  the  branch-

               instructions  can branch in an area of  32K.  When 

               using a branch with a byte offset you can put a .S 

               suffix behind the instruction e.g.  BEQ.S  .  When 

               using a branch with a word offset you can put a .W 

               suffix behind the instruction e.g.  BEQ.W  .  Most 

               assemblers  will  determine if the short  or  word 

               form is needed. Also most assemblers will optimize 

               word-branches to byte-branches whenever possible.



Condition codes affected:

               None

Function: Test  a  combination of the NZVC-flags in  the  status-

          register and conditionally perform a branch to  another 

          address. If the testing of the condition codes is true, 

          then  the  branch  will be  taken,  in  the  other  the 

          instruction  immediately following the Bcc  instruction 

          will  be executed. A total of 15 possible variations of 

          this instruction are listed below.

          BCC: where  CC stands for Carry Clear.  The  branch  is 

               taken if the C-bit is 0. This instruction is often 

               used   in  combination  with  shift   and   rotate 

               instructions.

          BCS: where CS stands for Carry Set. The branch is taken 

               if  the  C-bit  is  1.  This  instruction  is  the 

               counterpart of the BCC-instruction.

          BEQ: where EQ stand for EQual.  The branch is taken  if 

               the  Z-bit is 1.  This instruction is  often  used 

               after a TST-instruction or CMP-instruction.

          BNE: where NE stands for Not Equal. The branch is taken 

               if  the  Z-bit  is  0.  This  instruction  is  the 

               counterpart of the BNE-instruction.

          BPL: where PL stands for PLus.  The branch is taken  if 

               the  N-bit is 0.  This instruction is  often  used 

               after a TST-instruction or CMP-instruction.

          BMI: where MI stands for MInus.  The branch is taken if 

               the   N-bit  is  1.   This  instruction   is   the 

               counterpart of the BPL-instruction.

          BVC: where VC stands for oVerflow Clear.  The branch is 

               taken if the V-bit is 0. This instruction is often 

               used after an Integer Arithmetic instruction  like 

               ADD, SUB, MUL etc.

          BVS: where  VS stands for oVerflow Set.  The branch  is 

               taken if the V-bit is 1.  This instruction is  the 

               counterpart of the BVC-instruction.

          BRA: where   RA   stands  for   bRanch   Always.   This 

               instruction is often used at the end of a loop  to 

               go back to the beginning of the loop.

         Branches often used after an arithmetic operation on

         two's complement numbers.

          BGE: where GE stands for Greater or Equal.  This branch 

               is  taken  if the N and V-bits  contain  the  same 

               value.



          BGT: where GT stands for Greater Than.  This branch  is 

               taken in the following cases:

               - N is 1, V is 1, Z is 0

               - N is V is Z is 0

          BLE: where LE stands for Lower or Equal. This branch is 

               taken in the following cases:

               - Z is 1

               - N and V-bits contain different values

          BLT: where  LT  stands for Less Than.  This  branch  is 

               taken  if  the  N  and  V-bits  contain  different 

               values.

         Brances often used after an arithmetic operation on

         unsigned numbers.

          BHI: where HI stands for HIgher.  This branch is  taken 

               if the N and V-bits contain the same value.

          BLS: where LS stands for Lower or Same.  This branch is 

               taken  if  the  C  and  Z-bits  contain  different 

               values.

Example:

          This  shows  a piece of a C-program and  an  equivalent 

          piece  of  a PASCAL-program which are  translated  into 

          assembler. (variabele is signed)

          C:

               if (variable == 1 || variable > 4) variable = 5;

               else var *= 3;

          PASCAL:

               if (variable == 1) or (variable > 4)

               then variable := 5

               else variable := variable * 3



          * Most assemblers will optimize the branch-instructions

          * to the short forms

                 CMP.W   #1,variable

                 BEQ     L10000

                 CMP.W   #4,variable

                 BLE     L2

          L10000:

                 MOVE.W  #5,variable

                 BRA     L3

          L2:

                 MOVE.W  variable,R0

                 MULS    #3,R0

                 MOVE.W  R0,variable

          L3:

Instructions:  DBcc  (cc stands for Condition Code)

Syntax:        DBcc  Dn,<address>

Data sizes:    byte  or word.  This implicates that  the  branch-

               instructions can branch in an area of 32K.  Dn  is 

               considered to contain a word.

Condition codes affected:

               None

Function:

          The  group of Decrement and Branch (DBcc)  instructions 

          provide  an efficient way of creating loops.  They  are 

          nearly  always placed at the end of a loop.  First  the 

          condition   is  tested,   then  the   dataregister   is 

          decremented.  The  branch  is taken  in  the  following 

          cases:

          - Dn is -1;

          - The condition cc in DBcc is satisfied.

          There  are 16 possible variations of this  instruction. 

          They  all are nearly the same as the  Bcc-instructions, 

          with two exceptions. These are:

          DBF or DBRA:

               This  loop can only be terminated by  count  since 

               the other condition can never be satisfied.

          DBT: Only performs a decrement on the dataregister  and 

               never branches.  To me this seems a pretty useless 

               instruction,  which is only there to make the DBcc 

               series logically complete.

Example:

          This  piece of code is an efficient  implementation  of 

          the strcpy-function of the C-language.  A0 contains the 

          address  of  the  source string  and  A1  contains  the 

          address  of the destination string.  In C the end of  a 

          string is marked by a byte containing 0.

                 MOVE.W  #$ffff,D0

          LOOP:  MOVE.B  (A0)+,(A1)+

                 DBEQ    D0,LOOP

          This  piece of code can easily be transformed into  the 

          strncpy-function  by  loading D0 with  the  appropriate 

          value.





Instructions:  Scc  (cc stands for Condition Code)

Syntax:        Scc  <address>

Data sizes:    byte.



Condition codes affected:

               None

Function: Sets a byte to $ff if the condition codes satisfie.  If 

          the  condition is not satisfied the byte is set  to  0. 

          This  group of 16 instructions is rarely  used.  Nearly 

          all forms are the same as the DBcc group except for the 

          following two instructions:

          SF:  the same as a CLR.B instruction

          ST:  the same as a MOVE.B #$ff, <address>

Example:

          Be inventive, invent one yourself!





Instruction:   BSR, JSR

Syntax:        BSR  <address>

               JSR  <address>

Data sizes:    none

Condition codes affected:

               none







Addressing modes allowed (only for JSR):

Destination:

          (An)

          w(An)

          b(An,Rn)

          w

          l

          w(PC)

          b(PC,Rn)

Function: The  BSR  (Branch  to  SubRoutine)  and  JSR  (Jump  to 

          SubRoutine)   instructions   are   used   for   calling 

          subroutines.  BSR  can branch in a range  of  32K.  JSR 

          should  be  used when a jump out of the  32K  range  is 

          needed.   Some   assemblers  optimize  JSR   into   BSR 

          instructions  whenever  possible,  since  BSR  is  more 

          efficient   than   JSR.   When  executing   a   BSR/JSR 

          instruction,  the  68000 first pushes the PC  (program-

          counter) on the stack and then load the PC with the new 

          address. See below for the RTS (ReTurn from Subroutine) 

          instruction.





Instruction:   RTS

Syntax:        RTS

Data sizes:    none

Condition codes affected:

               none

Function: Counterpart  of BSR/JSR instructions.  Reloads  the  PC 

          with  the value on top of the stack.  This  value  will 

          nearly  always have been put on top of the stack  by  a 

          BSR/JSR instruction.

Example:  * the strcpy function discussed before

          STRCPY:

                 MOVE.W  #$FFFF,D0

          LOOP:  MOVE.W  (A0)+,(A1)+

                 DBEQ    D0, LOOP

                 RTS

          * some other code

          BEGIN:

                 MOVE.L  #SOURCE,A0

                 MOVE.L  #DEST,A1

                 JSR     STRCPY

                 RTS



          * the strings are put in a data area

          .DATA

          * 80 bytes for every string

          SOURCE .DS.B   80

          DEST   .DS.B   80

          * .DS.B means Define Storage Byte

          * so 80 bytes are define as storage for each string





Instruction:   JMP

Syntax:        JMP  <ea>

Data sizes:    none

Condition codes affected:

               none

















Addressing modes allowed:

Destination:

          (An)

          w(An)

          b(An,Rn)

          w

          l

          w(PC)

          b(PC,Rn)

Function: Transfer program control to another address.  The PC is 

          loaded  with the specified address.  In fact this is  a 

          variant  of  the MOVE instruction.  In  this  case  the 

          destination register is inherently defined,  namely the 

          PC-register.  Therefore we could translate JMP <ea>  to 

          MOVE.L <ea>,PC .



Instruction:   RTR

Syntax:        RTR

Data sizes:    none

Condition codes affected:

               none



Function: ReTurn    and   Restore.    Counterpart   of    BSR/JSR 

          instructions.  Reloads the PC with the value on top  of 

          the stack.  This value will nearly always have been put 

          on top of the stack by a BSR/JSR instruction.  The only 

          difference  with the RTS is that with this  instruction 

          also  the CCR is reloaded.  This instruction is  rarely 

          used  but  comes  in  handy when  one  doesn't  want  a 

          subroutine to influence the condition codes. Before the 

          JSR instruction you should use the instruction:

          MOVE.B CCR,-(A7)

          which pushes the CCR on the stack



Next time:  The last part of the instruction set.  These are  the 

instructions  which can only be executed when supervisor-mode  is 

active.







ASSEMBLY LANGUAGE COURS PART IX by Mark van den Boer



System Control instructions



In this part of the course the last group of instructions will be 

explained.  This group of instructions deals with the supervisor-

mode  and are therefore sometimes referred to as  system  control 

instructions.  To  remind  you:  the  S-bit  in  the  SR  (status 

register)  of  the  68000  determines whether  the  68000  is  in 

supervisor-mode or not.  Many of these instructions deal with  so 

called  exceptions.  Exception is another word for interrupt  and 

these are used to force program control immediately to a specific 

routint exception handler routine.  Exceptions are used to detect 

situations  that  are  urgent and need to  be  handled  directly. 

Therefore  every  exception has a vector  assigned  to  it.  This 

vector is a pointer to a routine which performs some action which 

should  be  taken when such an exception  occurs.  The  exception 

vectors are located in the first 256 longwords of memory.









Instruction:   CHK

Syntax:        CHK <ea>,Dn

Data sizes:    word

Condition codes affected:

               X    not affected

               N    Set if Dn is less than zero,  cleared if <ea> 

                    less than Dn, in all other cases undefined

               Z

               V

               C    always undefined

























Addressing modes allowed:

Source:

          Dn

          (An)

          (An)+

          -(An)

          w(An)

          b(An,Rn)

          w

          l

          w(PC)

          b(PC,Rn)

          #

Destination:

          Dn















Function: Compares the contents of the effective address  operand 

          with  the data-register.  If the data register is  less 

          than zero (the data register is always considered to be 

          a  signed word) or greater than the contents  of  <ea>, 

          then   an  exception  occurs.   The  pointer  to   this 

          exception-routine  is  located  at  address  $18.  This 

          instruction  is  used to check if a  data  register  is 

          within  a  range.   It  is  often  used  by  high-level 

          languages   such  as  PASCAL  to  perform   array-bound 

          checking.

Examples:

Instruction              Before              After

CHK #50,D0               D0=45               D0=45

                         No exception occured, if D0 had been 51

                         or greater then an exception would have

                         occured.





Instruction:   MOVE USP       (privileged instruction)

Syntax:        MOVE USP,An    or   MOVE An,USP

Data sizes:    long



Condition codes affected:

               X

               N

               Z

               V

               C    not affected

Addressing modes allowed:

     See syntax

Function: As  you all should know,  the 68000 has in fact two  A7 

          registers.  One A7 register is used when in supervisor-

          mode,  the  other  when in usermode (this  is:  not  in 

          supervisor-mode.   It  is  sometimes  desirable  for  a 

          program  which is executing in supervisor mode to  know 

          the value of the usermode A7-register. This instruction 

          provides  a  way to obtain and change the value  of  A7 

          usermode-register.

Example:

Instruction              Before              After

MOVE USP,A6              A7user=$12345678    A7user=$12345678

                         A6    =$00000000    A6    =$12345678

                         A7sup =$87654321    A7sup =$87654321



Instruction:   RESET

Syntax:        RESET          (privileged instruction)

Data sizes:    none

Condition codes affected:

               X

               N

               Z

               V

               C    not affected

Function: Reset all external devices. A device can be a chip like 

          the 6850.





Instruction:   RTE            (privileged instruction)

Syntax:        RTE

Data sizes:    none

Condition codes affected:

               none









Function: Every exception is terminated by this  instruction.  It 

          can be compared to RTS. The only difference is that RTE 

          will  restore  the  SR  in  addition.   Note  that   an 

          exception-routine   has  the  responsibility  to   save 

          registers if this is important.





Instruction:   STOP           (privileged instruction)

Syntax:        STOP #

Data sizes:    word

Condition codes affected:

          All set as a direct result of the operand

Addressing modes allowed:

Source:

          #

Function: Stop execution of a program until an exception  occurs. 

          The  operand  stored  in the SR.  Note  that  with  the 

          operand  a minimum interrupt level can  be  determined. 

          With  this  instruction it is possible to  wait  for  a 

          videochip interrupt to occur.





Example:

          STOP #%0010011000011111

          Wait  for  an exception with a priority of 6  or  7  to 

          occur and set the XNZVC-bits.





Instruction:   TRAP

Syntax:        TRAP #

Data sizes:    # must be >=0 and <=15

Condition codes affected:

               X

               N

               Z

               V

               C    not affected















Function: This  instruction generates an exception.  The  operand 

          indicates  an  exception number.  The vectors  for  the 

          exceptions  are located at addresses $80 to  $BC.  This 

          instruction  is  mainly  used to  allow  programs  that 

          execute in user-mode to call supervisor-mode  routines. 

          This  way  a  user can be given a  number  of  specific 

          functions. In the ST trap vectors 2, 14 and 15 are used 

          for GEM,  BIOS and XBIOS functions.  In the case of the 

          ST  the TRAP-instructions is preceded  by  instructions 

          that  put  function numbers and  parameters  for  these 

          functions  on  the stack.  This way it is  possible  to 

          assign groups of functions to one trap-vector.

          Note  that  when  calling  a  TRAP  in  user-mode   the 

          stackpointers  change (supervisor-mode  and  user-mode, 

          remember??). Thus, the MOVE USP instruction can be used 

          to retrieve parameters that had been put on the stack.





Instruction:   TRAPV

Syntax:        TRAPV

Data sizes:    none



Condition codes affected:

               none

Function: When  the  V-bit  is  set  an  exception  occurs.   The 

          exception vector is located at address $1C. When the V-

          bit is clear nothing happens.  This instruction can  be 

          used by high-level languages to inform the user that an 

          overflow error has occured.







MC 68000 ASSEMBLY LANGUAGE COURSE PART X by Mark van den Boer



Now  all instructions of the 68000 have been explained it's  time 

to  bring  this knowledge into practice.  This last part  of  the 

course  will  deal  with the subject  of  translating  high-level 

constructs to the equivalent assembler constructs. The C program-

ming  language will be used as the high-level language which  has 

to  be translated to assembler.  A note to those of you  who  are 

more familiar with Pascal or BASIC:  litte imagination is needed 

to deduct the similar constructs in Pascal and BASIC.

What now follows is a C-program which containing several commonly 

used data- and control structures.  The examples show you how  to 

translate these structures into assembler.

There  should  also be a file called M68000.DOC on your  ST  NEWS

disk.  This  file contains a quick-reference card containing  all 

instructions  and allowed addressing modes.  This reference  card 

has been made by Trustware,  Inc.  (an unregistered trademark  of 

Victor Langeveld).  I am very grateful to Victor for allowing  me 

to  include  this card,  since it's a rather tedious job  to  put 

together such a card.  One thing's for sure:  this card is one of 

the  better of its kind and it's the most compact reference  card 

for the 68000 I've ever seen.

/*

        A function. (Called a procedure or function in Pascal

        and a subroutine in BASIC)

        Note how parameters are passed in the assembly language

        translation.

        Als pay attention to how local variables are stored.

*/

int function (number, pointer)

int     number;

char    *pointer;

{

        register int    i, j;

        char    *c;



        i = number - 1;

        c = pointer;

        c = "new Queensryche album: Operation Mindcrime";

        /* Note how a string is stored */

        return i;          /* Note how a value is returned */

}





.text

function:

* offset of number = 8

* offset of pointer = 10

        LINK    A6,#-4

* save registers

        MOVEM.L D6-D7,-(sp)     * sp = A7

* i in D7

* j in D6

* offset of c = -4

* i = number - 1

        MOVE.W  8(A6),D7

        SUB.W   #1,D7

* c = pointer

        MOVE.L  10(A6),-4(A6)

* c = "new Queensryche album: Operation Mindcrime"

.data











L2:

        .dc.b 'new Queensryche album: Operation Mindcrime',0

        MOVE.L  #L2,-4(A6)

* D0 is used for resulting values from functions

* return i; D0 is always used for the result of a function

        MOVE.W  D7,D0

* restore registers

        MOVEM.L (sp)+,D6-D7

        UNLK    A6

* }

        RTS



* global variables

.bss

* int     i;

i:      .ds.w   1

* char    character

character:      .ds.b   1

* int     *i_pointer

i_pointer:      .ds.l   1





* int     i_array[10][5]

i_array:        .ds.w   10*5

* one struct is in fact 3 bytes long, but for every structure

* 4 bytes are reserved. This is because the 68000 can only

* address words at even addresses.

* struct { /* this is the equivalent of a record in PASCAL */

*         int     i;

*         char    c;

* } structure[5];

structure:      .ds.b   4*5





main()

{

        /* assignment of a constant to a variable */

        i = 9;



        /* assignment of a constant to a variable */

        character = 'c';



        /* assignment of a constant to a variable */

        i_pointer = &i;

        /* watch how indexing of array is done */

        /* integer is 2 bytes, so the address of

           array-element [3][4] is:

           (3 * 5 (the length of i_array[3]) + 4)

           * 2 (size of an integer) = 38.

           So the integer should be stored at i_array + 38.

        */

        i_array[3][4] = *i_pointer;



        /* Now the distance in bytes from the beginning of the

           array must be computed during program execution,

           in contrary to the previous example.

        */

        i_array[i][i - 1] = 2;



        /* Assignments to arrays of structures */

        structure[1].i = 3;

        structure[i].c = character;



        /* expression evaluation and assignment */

        i = i_array[0][0] * i_array[0][1] +

            i_array[0][2] / i_array[0][3];

        /* conditional statement */

        if (i < i_array[i][i]) i = 1;

        else i = 2;



        /* while loop */

        while (i <= 10) i++;

        /* continue and break statements */

        while (i++ <= 10) {

                if (i != 4) continue;

                else break;

        }



        /* for loop */

        for (i = 4; i >= 0; i--) i_array[i][i] = i;



        /* do loop */

        do i++; while (i < 10 && i != 5);



        /* switch statement; watch the application of a

           jump-table. Pay special attention to how 'case 4'

           which must 'default' is solved.



        */

        switch (i) {

        case 0:

                i = 0;

                break;

        case 1:

                i = 5;

                break;

        case 2:

        case 3:

                i = 7;

                break;

        case 5:

                i = 1;

                break;

        default:

                i = 2;

                break;

        }







        /* switch statement;

           watch how 'case 999' has destroyed the

           jumptable-optimization.

        */

        switch (i) {

        case 0:

                i = 0;

                break;

        case 1:

                i = 5;

                break;

        case 2:

        case 3:

                i = 7;

                break;

        case 5:

                i = 1;

                break;

        case 999:

                /* This case should be tested seperately so

                   the assembler code can be more efficient.



                */

                i = 100;

                break;

        default:

                i = 2;

                break;

        }



        /* manipulating bits */

        i = i & 0x2345;

        i = i | 0x2345;

        i = i ^ 0x2345;

        i = ~i;

        i <<= i;



        /* using the result of a function */

        i = function(5, &character);



}



.text



main:

* Reserve 4 bytes. This way, when the first parameter for a

* function is pushed onto the stack, no pre-decrementing of sp

* has to be done. This 'trick' is used by the DRI-C-compiler.

        LINK    A6,#-4

* i = 9

        MOVE.W  #9,i

* character = 'c'

        MOVE.B  #'c,character

* i_pointer = &i

        MOVE.L  #i,i_pointer

* i_array[3][4] = *i_pointer

        MOVE.L  i_pointer,A0

        MOVE.W  (A0),38+i_array

* i_array[i][i - 1] = 2

        MOVE.W  i,D0     * compute byte offset from first element

        MULS    #10,D0

        MOVE.W  i,D1

        SUB.W   #1,D1

        ASL.W   #1,D1   * multiply by 2 because an int is 2 bytes

        EXT.L   D1

        ADD.L   D1,D0

        ADD.L   #i_array,D0

        MOVE.L  D0,A0   * move computed address to address-reg

        MOVE.W  #2,(A0)

* structure[1].i = 3

        MOVE.W  #3,4+structure

* structure[i].c = character

        MOVE.W  i,A0

        ADD.L   A0,A0

        ADD.L   A0,A0

* Two ADD operations are faster than a MUL and a MOVE

        ADD.L   #structure,A0

        MOVE.B  character,2(A0)

* i = i_array[0][0] * i_array[0][1] +

*     i_array[0][2] / i_array[0][3];

        MOVE.W  i_array,D0

        MULS    2+i_array,D0

        MOVE.W  4+i_array,D1

        EXT.L   D1

        DIVS    6+i_array,D1

        ADD.W   D1,D0

        MOVE.W  D0,i

* if (i < i_array[i][i]) i = 1;

* else i = 2;

        MOVE.W  i,D0

        MULS    #10,D0

        MOVE.W  i,D1

        ASL.W   #1,D1

        EXT.L   D1

        ADD.L   D1,D0

        MOVE.L  D0,A0

        MOVE.L  #i_array,A1

        MOVE.W  0(A0,A1.L),D0

        CMP     i,D0

        BLE     L4

* i = 1

        MOVE.W  #1,i

        BRA     L5

L4:

* i = 2

        MOVE.W  #2,i

L5:

        BRA     L8





* while (i <= 10) i++;

* This loop has been optimized:

* one BRA instruction was saved by putting the test after the

* do-part. The label L5:    BRA L8    takes care that the while

* condition is executed first at the beginning of the loop

L7:

        ADD.W   #1,i

L8:

        CMP.W   #10,i

        BLE     L7

* while (i++ <= 10) {

*   if (i != 4) continue;

*   else break;

* }

L6:

        BRA     L11

L10:

        CMP.W   #4,i

        BNE     L11

        BRA     L9





L11:

        CMP     #10,i

        MOVE.W  SR,D0   * save condition codes

        ADD.W   #1,i

        MOVE    D0,CCR  * and restore

        BLE     L10

* for (i = 4; i >= 0; i--) i_array[i][i] = i

L9:

        MOVE.W  #4,i

        BRA     L14

L15:

        MOVE.W  i,D0

        MULS    #10,D0

        MOVE.W  i,D1

        ASL.W   #1,D1

        EXT.L   D1

        ADD.L   D1,D0

        ADD.L   #i_array,D0

        MOVE.L  D0,A0

        MOVE.W  i,(A0)

L13:

        SUB.W   #1,i

L14:

        TST     i

        BGE     L15

L12:

* do i++; while (i < 10 && i != 5);

L18:

        ADD.W   #1,i

L17:

        CMP.W   #10,i

        BGE     L10000

        CMP.W   #5,i

        BNE     L18

L10000:

* switch (i) {

* case 0:

*        i = 0;

*        break;

* case 1:

*        i = 5;

*        break;





* case 2:

* case 3:

*        i = 7;

*        break;

* case 5:

*        i = 1;

*        break;

* default:

*        i = 2;

*        break;

* }

L16:

        MOVE.W  i,D0

        BRA     L20

L21:

        CLR.W   i

        BRA     L19

L22:

        MOVE.W  #5,i

        BRA     L19





L23:

L24:

        MOVE.W  #7,i

        BRA     L19

L25:

        MOVE.W  #1,i

        BRA     L19

L26:

        MOVE.W  #2,i

        BRA     L19

L20:

* Test if i is in case-range

* if not goto default

* if in range compute address to jump to

        CMP.W   #5,D0

        BHI     L26

        ASL.W   #2,D0

        MOVE.W  D0,A0

        ADD.L   #L27,A0

        MOVE.L  (A0),A0

        JMP     (A0)

.data

L27:

* jumptable

.dc.l L21

.dc.l L22

.dc.l L23

.dc.l L24

.dc.l L26

.dc.l L25

.text

L19:

* switch (i) {

* case 0:

*         i = 0;

*         break;

* case 1:

*         i = 5;

*         break;

* case 2:

* case 3:

*         i = 7;

*         break;



* case 5:

*         i = 1;

*         break;

* case 999:

*         /* This case should be tested seperately so

*            the assembler code can be more efficient.

*         */

*         i = 100;

*         break;

* default:

*         i = 2;

*         break;

* }

        MOVE.W  i,D0

        BRA     L29

L30:

        CLR.W   i

        BRA     L28

L31:

        MOVE.W  #5,i

        BRA     L28



L32:

L33:

        MOVE.W  #7,i

        BRA     L28

L34:

        MOVE.W  #1,i

        BRA     L28

L35:

        MOVE.W  #100,i

        BRA     L28

L36:

        MOVE.W  #2,i

        BRA     L28

        BRA     L28

L29:

        EXT.L   D0

        MOVE.L  #L37,A0

        MOVE.W  #6,D1









L38:

        CMP.L   (A0)+,D0

        DBEQ    D1,L38

        MOVE.L  24(A0),A0

        JMP     (A0)

.data

L37:

* table of case values

.dc.l 0

.dc.l 1

.dc.l 2

.dc.l 3

.dc.l 5

.dc.l 999

.dc.l 0

* jump table

.dc.l L30

.dc.l L31

.dc.l L32

.dc.l L33

.dc.l L34

.dc.l L35

.dc.l L36

.text

L28:

* i = i & 0x2345

        ANDI.W  #$2345,i

* i = i | 0x2345

        ORI.W   #$2345,i

* i = i ^ 0x2345

        EORI.W  #$2345,i

* i = ~i

        NOT.W   i

* i <<= i

        MOVE.W  i,D1

        MOVE.W  D1,D0

        ASL.W   D1,D0

        MOVE.W  D0,i

* i = function (5, &character)

        MOVE.W  #51,(sp)

        MOVE.L  #character,-(sp)

        ADDQ.L  #4,sp

        MOVE.W  D0,i



L3:

        UNLK    A6

        RTS





Hope you had much fun with this course and that you learnt a lot!