Amiga Machine Language (Chapter 2)

A amigaspirit.hu - pegasos.hu Wiki wikiből

The following text is part of the Amiga Machine Language tutorial.


Tartalomjegyzék

Chapter 2, The MC68000 processor

The Amiga`s MC68000 processor is a 16/32 bit processor, which means that while it can process data of 32 bits, it "only" has a 16 bit data bus and a 24 bit address bus. Thus, it can access 2^24=16777216 bytes (or 16 Mbytes) of memory directly.

7.1 Megahertz

The Amiga 68000 processor, running at 7.1 megahertz, is quite fast, which is required for a computor with a workload as heavy as the Amiga`s. The Amiga also processes a number of custom chips that greatly ease the workload of the processor. These custom chips manage sound in/output, graphics and animation, thus freeing the processor for calculations.


Registers

In addition to the standard RAM, the processor contains internal memory called registers. There are eight data registers (D0-D7), eight address registers(A0-A7), a status register(SR),two stack pointers, a user stack pointer, a system stack pointer (USP and SSP) and the program counter(PC).

  • Register Sizes: The data registers,the address registers, and the program counter are all 32 bits, while the status register is 16 bits. These registers are located directly in the processor so they are not accessed the same way memory would be accessed. There are special instructions for accessing these registers.
  • Data Registers: The data registers are used for all kinds of data. They can handle operations with bytes (8 bits), words (16 bits) and longwords (32bits).
  • Address Registers: The address registers are used for storing and processing addresses. This way they can be used as pointers to tables, in which case only words and longwords operations are possible.
  • Stack Pointer: The address register A7 plays a special role:this register is utilized as the Stack Pointer(SR) by the processor, and thus is not recommended for normal use by the programmer. Which of the two possible stacks is being pointed to depends on the present mode of the processor, but more about that later. The stack, to whose actual position the stack pointer is pointing, is used to store temporary internal data. The stack works similar to a stack of notes on your desk: the note that was added to the stack last is the first one to come off the stack. This type of stack is known as LIFO (Last in,First out). There is another type of stack, the FIFO (First in,First out) which is not used by the processor itself. How these registers and the SP can be manipulated, or how to work with the stack, is presented in the next chapter. Lets continue with the registers for now.
  • Status Register: The status register plays an important role in machine language programming. This 16-bit quality (word) contains important information about the processor status in 10 of its bits. The word is divided into two bytes, the lower byte (the user byte) and the upper byte (the system byte). The bits that signify that certain conditions are refered to as flags. This means that when a certain condition is present, a particular bit is set. The user byte contains five flags, which have the following meaning:
               Bit     Name           Meaning
               -----------------------------------------------
                0      (C,Carry)      Carry bit,modified by math
                                      calculation,and shift instructions.
                1      (V,Overflow)   Similar to carry,indicates a change
                                      of sign,in other words,a carry from
                                      bit six to bit seven.
                2      (Z,Zero)       Bit is set when the result of an
                                      operation is zero.
                3      (N,Negative)   Is set when the result of an
                                      operation  is negative.
                4      (X,Extended)   Like carry,is set for arithmetic
                                      operations.
                5-7                   Not used.

The system byte contains five significant bits:

               Bit     Nane           Meaning
               -----------------------------------------------
                8      I0             Interupt mask.Activates interupt
                9      I1             levels 0 to 7,where 0 is the lowest
                10     I2             and 7 is the highest priority.
                11                    not used.
                12                    not used.
                13    (S,Supervisor)  This bit indicates the actual
                                      pocessor mode(0=User,1=Supervisor
                                      mode).
                14                    not used.
                15    (T,Trace)       If this bit is set,the processor is
                                      in single step mode.

Here's an overview of the status word;

                bit  : 15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0
                name :  T  -  S  -  - I2 I1 I0  -  -  -  X  N  Z  V  C
       

Don't let the new terms, like mode and interupt confuse you. We'll talk about these in greater detail in the chapter dealing with the operating conditions of the processor.


Addressing Memory

In the standard Amiga 500's and 1000's, the processor has over 512k of RAM available. The Amiga 2000 has one mega-byte of RAM that can be accessed by the processor. How does the processor access all this memory? If you're programming in BASIC you don't have to worry about memory management. You can simply enter MARKER%=1, and the value is stored in memory by the BASIC interpreter. In assembler, there are two ways of accomplishing this task:

  1. Store the value in one of the data or address registers,or
  2. Write it directly into a memory location.

To demonstrate these two methods let's get a little ahead and introduce a machine language instruction, which is probably the most common: MOVE. As its name states,this instruction moves values. Two parameters are required with the instruction: source and destination. Lets see what the example from above would look like if you utilize the MOVE instruction...

  1. MOVE #1,D0 - This instruction moves the value 1 into data register D0. As you can see,the source value is always entered before the destination. Thus, the instruction MOVE D0,#1 is not possible.
  2. MOVE #1,$1000 - deposits the value 1 in the memory location at $1000. This address was arbitrarily chosen. Usually addresses of this form won't be used at all in assembler programs, since labels that point to a certain address are used instead. Thus, the more common way of writing this would be:
            ...
            MOVE  #1,MARKER
            
            ...
         MARKER:DC.W 1

These are actually two pieces of program: the first part executes the normal MOVE instruction whose destination is `MARKER`. This label is usually defined at the end of a program and specifies the address at which the value is stored. The parameter DC.W 1 is a pseudo op, a pseudo operation. This means that this isn`t an instruction for the processor, but an instruction for the assembler. The letters DC stand for `DeClare` and the suffix .W indicates that the data is a Word. The other two suffix alternatives would be .B for a byte(8 bits) and .L for a long word(32 bits). This suffix (.B.W or.L) is used with most machine language instructions. If the suffix is omitted,the assembler uses .W(word) as the default parameter. If you wanted a long word, you`d use an instruction that looks something like this: MOVE .L #$1234678,D0 where as an instruction like MOVE.B #$12,D0 would be used for a byte of data. However,with this instruction there`s one thing you must be aware of...

  • CAUTION: If the memory is accessed by words or long words,the address must be even (end digit must be 0,2,4,6,8,A,C,E)!

Assemblers usually have a pseudo-op, `EVEN` or `ALIGN`, depending on the assembler, that aligns data to an even address. This becomes necessary in situations similar to this:

            ...
         VALUE1:    DC.B 1
         VALUE2:    DC.W 1

If the VALUE1 is located at an even address, VALUE2 is automaticaly located at an odd one. If an ALIGN (EVEN) is inserted here, a fill byte(0) is inserted by the assembler, thus making the second address even.

            ...
         VALUE1:    DC.B 1
         ALIGN
         VALUE2:    DC.W 1

Back to the different ways of addressing. The variations listed above are equivalent to the BASIC instruction MARKER%=1 where the % symbol indicates an integer value. Lets go a step further and translate the BASIC instruction MARKER%=VALUE% into assembler. You`ve probably already guessed the answer right?

                MOVE VALUE,MARKER
                ...
                ...
         MARKER:      DC.W 1
         VALUE :      DC.W 1

In this case, the contents in the address at VALUE are moved into the address at MARKER. With the help of these simple examples, you`ve already become familiar with four different ways of addressing, in other words, ways that the processor can access memory. The first is characterized by the number sign (#) and represents a direct value. Thus, this method is also known as direct addressing, and is legal only for the source parameter!

A further method in which a direct address (in our case, `MARKER` and `VALUE`) can be specified is known as absolute addressing. This method is legal for the source parameter as well as for the destination parameter. This method can be divided into two different types, between which the programmer usually does'nt notice a difference. Depending on whether the absolute address is smaller or larger than $FFFF, in other words if it requires a long word, it is called absolute addressing (for addresses above $FFFF) or otherwise absolute short addressing. The assembler generally makes the distinction between these two types, and thus, only general knowledge of absolute addressing is required.

The fourth method of addressing that you've encountered so far is known as DATA REGISTER DIRECT. It was the first one introduced(MOVE #1,D0) in conjunction with direct addressing, the only difference being that this type accesses a data register (such as D0). These four methods aren't the only ones available to the MC68000 processor, in fact there are a total of 12. One other variation called ADDRESS REGISTER DIRECT, is almost identical to data register direct, except that it accesses the address register instead of the data register. Thus, you can use MOVE.L #MARKER,A0 to access the address register A0 directly.

You now know five ways to address memory with which quite a bit can be accomplished. Now, lets tackle something more complicated and more interesting. Lets take another example from BASIC:

           10  A=1000
           20  POKE A,1

In this example the first line assigns the value 1000 to the variable A. This can be done in assembler as well: MOVE.L #1000,A0. In the assembler version the absolute value of 1000 is stored in the address register A0. Line 20 doesn't assign a value to the variable A itself, but rather to the memory location at the address stored in A. This is an indirect access, which is quite easy to duplicate in assembler:

           MOVE.L  #1000,A0       ;bring address in A0
           MOVE    #1,(A0)        ;write 1 into this address

The parentheses indicates an addressing known as ADDRESS REGISTER INDIRECT. This method only works with address registers, since a 'data register indirect' does not exist. There are several variations of this method. For instance, a distance value can be specified,which is added to the address presently located in the address register before the register is actually accessed. The instruction MOVE #1,4(A0), if applied to the example above, writes the value 1 into the memory cell at 1000+4=1004. This distance value can be positive or negative. Thus, values from -32768 to +32768 are accepted. This specific variation of addressing is called ADDRESS REGISTER INDIRECT WITH A 16 BIT DISPLACEMENT value. There is another very similar variation: ADDRESS REGISTER INDIRECT WITH AN 8 BIT INDEX value. While this variation is limited to 8 bits, it also brings another register into play. This second register is also a distance value, except that it is a variable as well.

We'll try to clarify this with an example. Lets assume that a program includes a data list that is structured like this:

              ...
           RECORD: DC.W 2                ;number of entries -1
                   DC.W 1,2,3            ;elements of list

We'll use MOVE.L #RECORD,A0 to load the list into the address register A0. Then you can use MOVE (A0),D0 to pull the number of in the list into the data register. To access the last element of the list only one instruction is needed. The whole thing looks something like this:

                   CLR.L   D0            ;erase D0 completely
                   MOVE.L  #RECORD,A0    ;address of list in A0
                   MOVE    (A0),D0       ;number of elements -1 in D0
                   MOVE    1(A0,D0),D1   ;last element in D1
                   ...
           RECORD: DC.W 2                ;number of entries -1
                   DC.W 1,2,3            ;elements of list

This last instruction accesses the byte that is located at 1+A0+D0 in other words,the record +1 where the data begins plus the contents of D0 (in this case 2). This method of accessing is very useful. It works exquisitely for the processing of tables and lists, as the example demonstrates. If no distance value is needed, simply use a distance value of zero, which some assemblers automatically insert as the default value if for instance only MOVE (A0,D0) is entered. The latter two methods have a third variation, which has its own characteristic trait. It dosen't utilize an address register, but uses the Program Counter(PC) instead. The program counter with displacement method proves useful when a program must function without any changes in all address ranges. The following two statements (in the 15 bit limits) have the same effect:

  1. MOVE MARKER,D0
  2. MOVE MARKER(PC),D0

This method is actually rather imprecise, since the first instruction specifies the actual address of the marker with MARKER while the second line specifies the distance between the instruction and the marker. However since it would be quite cumbersome to constanly calculate the distance,the assembler takes this task off our hands and calculates the actual value automatic. Lets examine the difference between the two instructions. In a program they'll accomplish the same thing, although they are interpreted as two completely different things by the assembler. You'll assume a program being at the address $1000 and the marker is located at $1100. The generated program code looks something like this:

          $001000      30 39 00 00 11 00     MOVE  MARKER,D1

or

          $001000      30 3A 00 FE           MOVE  MARKER(PC),D1

As you can see, the generated code of the second line is two bytes shorter than the first line. In addition, if you were to shift this code to the address $2000, the first version still accesses the memory at $1100, while the second line using the PC indirect addressing accesses memory at $2000 correctly. Thus, the program can be transferred to almost any location. This, then, is PROGRAM COUNTER WITH 16 BIT DISPACEMENT value. As we mentioned, there is also PROGRAM COUNTER WITH 8 BIT INDEX value, which permits a second register as a distance value, also known as offset.

There are two addressing modes left. These two are based on indirect addressing. They offer the capability of automatically raising or lowering the address register by one when memory is accessed with address register indirect. To automatically increase the register, you'd use ADDRESS REGISTER INDIRECT WITH POST-INCREMENT. The address register raises this by the number of bytes used AFTER accessing memory. Thus if you write:

            MOVE.L  #1000,A0
            MOVE.B  #1,(A0)+

the 1 is written in the address $1000 and then A0 is raised by one. Instructions like this are very helpful when a memory range is to be filled with a specific value (for instance when the screen is cleared). For such purposes the instruction can be placed in a loop ... which we'll get to later.

The counter part to post increment is ADDRESS REGISTER INDIRECT WITH PRE-DECREMENT. In this case the specified address register is lowered by one BEFORE the access to memory. The instructions:

            MOVE.L  #1000,A0
            MOVE.B  #1,-(A0)

writes 1 in the address 999, since the contents of A0 is first decremented and the 1 is written afterwards. These two methods of addressing are used to manage the stack pointer(SP). Since the stack is filled from top to bottom, the following is written to place a word (s.aD0) on the stack:

            MOVE.B  D0,-(SP)

and to remove it from the stack, again in D0:

            MOVE.B  (SP)+,D0

This way the stack pointer always points to the byte last deposited on the stack. Here, again, you'll have to be careful that an access to the stack with a word or a long word is always on an even address. Thus, if you're going to deposit a byte on the stack, either use a whole word or make sure the byte is not followed by a JSR or BSR. The JSR or BSR instructions deposit the addresses from which they stem on the stack in the form of a long word. In the code above,the SP is generally replaced by the address register A7 in the program code, since this register is always used as the SP. Thus,you can write A7 as well as S,the resulting program is the same. However, we recommend the use of SP, since this makes the code somewhat easier to read. After all, quite often you'll want to employ your own stacks, in which case the difference between the processor stack and your own stacks become very important.

These are the twelve ways of addressing the MC68000 processor, here is a summary:

       No  Name                                                Format
       --  ----                                                ------
        1  data register direct                                Dn
        2  address register direct                             An
        3  address register indirect                           (An)
        4  address register indirect with post-increment       (An)+
        5  address register indirect with pre-decrement        -(An)
        6  address register indirect with 16 bit displacement  d16(An)
        7  address register indirect with 8 bit index value    8(An,Rn)
        8  absolute short                                      xxxx.W
        9  absolute long                                       xxxxxxxx.L
       10  direct                                              #'data'
       11  program counter indirect with 16 bit displacement   d16(PC)
       12  program counter indirect with 8 bit index value     d8(PC,Rn)

The abbreviations above have the following meanings:

            An      address registers A0-A7
            Dn      data registers D0-D7
            d16     16 bit value
            d8      8 bit value
            Rn      register D0-D7,A0-A7
            'data'  up to 32 bit value,(either .B .W .L)

These are the addressing modes used by the MC68000 processor. The bigger brother of this processor, the 32 bit MC68020, has six more methods which we won't discuss here. Next you're going to see under what conditions the processor can operate.


Operating Modes

In the previous section about registers you encountered the Status Register (SR). The individual bits of this register reflect the present operating condition of the processor. You differentiated between the system byte (bits 8-15) and the user byte (bits 0-7). Now, lets take a closer look at the system byte and its effects upon the operation of the processor.


User and Supervisor Modes

Isn't it rather strange that the processor classifies you either as a 'user' or a 'supervisor'? Both of these operating modes are possible, the user mode being the more common mode. In this mode it is impossible to issue some instructions, and that in your own computor! Don't worry though,you can get around that,as well. The Amiga's operating system contains a function that allows us to switch the processor from one mode to the other.

The mode is determined by bit 13 of the Status Register. Usually this bit is cleared(0), indicating that the processor is in user mode. It is possible to write directly into the status register, although this is a privileged instruction that can only be executed from the supervisor mode. Thus, this instruction could only be used to switch from the supervisor mode into the user mode, by using AND #$DFFF,SR to clear the supervisor bit. However, it is quite preferable to let the operating system perform the switch between these two modes. Now what differentiates these two modes in terms of application?

Well, we already mentioned the first difference: some instructions, such as MOVE xx,SR, are privileged and can only be executed from the supervisor mode. An attempt to do this in user mode would result in an exception and interruption of the program. Exceptions are the only way of switching to the supervisor mode, but more about later. A further difference is in the stack range used. Although A7 is still used as the stack pointer, another memory range is used for the stack itself. Thus, the SP is changed rach time you switch from one mode to the other. Because of this you differentiate between the User(USP) and the Supervisor SP (SSP).

Accessing memory can also depend on these two modes. During such accessing, the processor sends signals to the peripheral components informing them of the current processor moce. This way a MC68000 computor can protect (privilege) certain memory ranges so they can't be accessed by the user. In the supervisor mode it is possible to execute all instructions and access all areas of memory. Because of this, operating systems usually run in the supervisor mode. This is accomplished through the use of Exceptions.

Exceptions

Exceptions are similar to interupts on 6500 computors. This allows stopping a program, running a sub-program,and then restarting the stopped program. When an exception occurs the following steps are taken:

          1)   The status register is saved.
          2)   The S bit in SR is set(supervisor mode)and the T bit is
               cleared(no trace).
          3)   The program counter and the user SP are saved.
          4)   The exception vector,which points to the needed exception
               routine,is retrieved.
          5)   The routine is executed.

The vectors mentioned, which contain the starting addresses for the various routines, are located at the very beginning of the memory. Here is an overview of the vectors and their respective addresses:

          Number   Address       Used for
          -----    ------        --------
           0       $000          RESET:starting SSP
           1       $004          RESET:starting PC
           2       $008          bus error
           3       $00C          address error
           4       $010          illegal instruction
           5       $014          division by zero
           6       $018          CHK instruction
           7       $01C          TRAPV instruction
           8       $020          privilege violation
           9       $024          trace
          10       $028          Axxx-instruction emulation
          11       $02C          Fxxx-instruction emulation
                   $030-$038     reserved
          15       $03C          uninitialed interrupt
                   $040-$05F     reserved
          24       $060          unjustified interrupt
          25-31    $064-$083     level 1-7 interrupt
          32-47    $080-$0BF     TRAP instructions
                   $0C0-$0FF     reserved
          64-255   $100-$3FF     user interrupt vectors

The individual entries in the table above need detailed explanation. So lets go through them one by one...

  • RESET: staring SSP; At reset, the long word stored at this location is used as the stack pointer for the supervisor mode(SSP). This way you can specify the stack for the RESET routine.
  • RESET: starting PC; Again at reset,the value at this location is used as the program counter. In other words, the RESET routine is started at the address stored here.
  • Bus Error: This exception is activated by a co-processor when, for instance, a reserved or non-existant memory range is accessed.
  • Address Error: This error occurs when a word or long word access is atempted at an odd address.
  • Illegal Instruction: Since all MC68000 instructions consist of one word,a total 65536 different instructions are possible. However,since the processor doesn't that many instructions, there are a number of words that are invalid instructions. Should such a word occur, the exception is prompted.
  • Division by Zero: Since the processor has a division function,and the division of anything by zero is mathematically undefined and thus illegal, this exception occurs when such an operation is attempted.
  • CHK Instruction: This exception only occurs with the CHK instruction. This instruction tests that a data registers contents are within a certain limit. If this is not the case, the exception is activated.
  • TRAPV Instruction: If the TRAPV instruction is executed and the V bit (bit 1) in the status word is set, this exception is prompted.
  • Privilege Violation: If a privileged instruction is called from the user mode, this exception is activated.
  • Trace: If the trace bit (bit 15) in the status word is set, this exception is activated after each instruction that is executed. This method allows you to employ a step by step execution of machine programs.
  • Axxx-Instruction Emulation:
  • Fxxx-Instruction Emulation: These two vectors can be used for a quite interesting trick. If an instruction beginning with $A or $F (such as $A010 or $F200) is called the, the routine to which the corresponding vector is pointing is accessed. In these routines you can create chains of other instructions, in effect expanding the processors instruction vocabulary!
  • Reserved: These vectors are not used.
  • Uninitialized Interrupt: This exception is activated when a peripheral component that was not initialized sends an interrupt.
  • Unassigned Interrupt: Is activated when a BUS error occurs during the interrupt verification of the activating component. However,the interrupt is usually only by some type of disturbance.
  • Level 1-7 Interrupt: These seven vectors point to the interrupt routines of the corresponding priority levels. If the level indicated in the status word is higher than the level of the occuring interrupt, the interrupt is simply ignored.
  • TRAP Instructions: These 16 vectors are used when a corresponding TRAP instruction occurs. Thus, TRAP instructions from TRAP #0 to TRAP #15 are possible.
  • User Interrupt Vectors: These vectors are used for interrupts which are activated by several peripheral components that generate their own vector number.

At this point you don't want to delve any deeper into the secrets of exceptions, since we'd be expanding this book beyond its frame work. However, there's one last thing to say about exceptions: theexception routines are ended with the RTE (ReTurn from Exception) instruction, with which the original status is restored and the user program is continued.


Interrupts

       Interrupts are processed similarly to exceptions.They are breaks
       (or interruptions)in the program which are activated through
       hardware(such as a peripherical component or an external trigger).
       The interrupt level is stored in bits 8-10 of the status register.
       A value between 0 and 7 indicates the interrupt level.There are
       eight possible interrupts,each of which as a different priority.If
       the level of this interrupt happens to be higher than the value in
       the status register,the interrupt is executed,or else ignored.
       When a valid interrupt occurs,the computor branches to the
       corresponding routine whose address is indicated in the exception
       vector table above.
       The interrupts are very important if you're trying to synchronize
       a program with connected hardware.In this manner,a trigger(s.a the
       keyboard)which is to feed the computor data,can signal the request
       for a legal value using an interrupt.The interrupt routine then
       simply takes the value directly.This method is also employed for
       the operation of the serial interface(RS232).
       We'll talk about the use of interrupts at a later time.The last
       thing we want to mention about interrupts at this time is that,
       like exceptions,interrupt routines are terminated with the RTE
       instruction.
     2.3.4.Condition Codes.
     ---------------------
       When you write a program in any language,the need for a
       conditional operation arises quite often.For instance,in a BASIC
       program
           IF D1=2 THEN D2=0
       represents a conditional operation.To write the equivalent in
       machine language,you first need to make the comparison:
           CMP  #2,D1
       CMP stands for compare and compares two operands,in this case D1
       and D2.How is this operation evaluated?
       For this purpose you have condition codes(CC's),which exist in the
       branch instructions of machine language.Because of this,you must
       specify when and where the program is to branch.
       The simplest variation of the branch instruction is an
       unconditional branch.The corresponding instruction is 'BRA address
       ',although this won't help you here.After all,you need a
       conditional branch.
       To retain the result of the operation,in this case a comparrison
       (CMP),several bits are reserved in the status word.Lets look at
       bit 2 first,which is the zero flag.This flag is set when the
       result of the previous operation was zero.
       To explain the relationship between CMP and the Z flag,you must
       first clarify the function of the CMP instruction.Actually this
       instruction performs the subtraction of the source operand from
       the destination operand.In the example above,the number 2 is
       subtracted from the content of the memory cell at D1.Before the
       result of this subtraction is discarded,the corresponding flags
       are set.
       If the contents of D1 in our example above happened to be 2,the
       result of the subtraction would be 0.Thus,the Z flag would be set,
       which can then be evaluated through a corresponding branch
       instruction.Our example would then look like this:
                  ...
                 CMP   #2,D1      ;comparison,or subtraction
                 BNE   UNEQUAL    ;branch,if not equal(Z flag not set)
                 MOVE  #0,D2      ;otherwise execute D2=0
        
          UNEQUAL:
                  ...             ;program branches to here
       BNE stands for Branch if Not Equal.This means,that if the Z flag
       was cleared(=0)by the previous CMP,the program branches to the
       address specified by BNE(here represented by UNEQUAL).The counter
       part to the BNE instruction is the BEQ(Branch if EQual)instruction
       which is executed if Z=1.
       Here's a list of condition codes,which allow you to form
       conditional branches using the Bcc(cc=condition code)format:
          cc       Condition                     Bits
          ---------------------------------------------------
          T        true,corresponds to BRA
          F        false,never branches
          HI       higher than                   C'* Z'
          LS       lower or same                 C + Z
          CC,HS    carry clear,higher or same    C'
          CS,LO    carry set,lower               C
          NE       not equal                     Z'
          EQ       equal                         Z
          VC       overflow clear                V'
          VS       overflow set                  V
          PL       plus,positive
          MI       minus,negative
          GE       greater or equal              N*V+N'*V'
          LT       less than                     N*V'+N'*V
          GT       greater than                  N*V*Z'+N'*V'*Z'
          LE       less or equal                 Z + N*V' + N'*V
          *=logic AND, +=logic OR, '=logic NOT
       Here are a few examples to demonstrate how these numerous
       conditions can be utilized:
          CMP   #2,D1
          BLS SMALLER_EQUAL
       This branches if the contents of D1<=2,whether D1 is 0,1 or 2.In
       this example,the BLE instruction would allow the program to branch
       even if D1 is negative.You can tell this by the fact that the V
       bit is used in the evaluation of this expression(see chart above).
       When the sign is changed during the operation,this V bit is
       compared with the N bit.Should both bits be cleared(N bit=0 and V
       bit=0)after the CMP subtraction(D1-2),the result has remained
       positive:the condition as not been met.
       The conditions EQ and NE are quite important for other uses,as
       well.For instance,they can be used to determine if particular bits
       in a data word are set,by writing the following sequence...
           ...
           AND  #%00001111,D1       ;masks bits out
           BEQ SMALLER              ;branches when none of the four
       ;                            ;lower bits is set
           CMP  #%00001111,D1 
           BEQ ALL                  ;branches when all four bits set
       The AND instruction causes all bits of D1 to be compared with the 
       bits of the parameter(in this case #%00001111).If the same bits
       are set in both bytes,the corresponding bits are also set in the
       result.If one bit of the pair is cleared,the resulting bit is zero
       as well.Thus,in the result,the only bits that are set are those
       bits of the lowest four that were set in D1.
       The technique is known as masking.In the example above,only the
       lowest four bits were masked out,which meansthat in the resulting 
       byte,only the lowest four appear in their original condition.All
       other bits are cleared with the AND operand.Of course you can use
       any bit combination with this method.
       If no bit at all is set in the result,the zeroflag is set,thus
       fullfilling the BEQ condition and branching the program.Otherwise,
       the next instruction is processed,in which D1 is compared with
       %00001111.When both are equal,at leastall of the four lowest bits
       of the original byte have been set,in which case the following BEQ
       instruction branches.
       Aside from CMP,the CC and CS conditions can also be used to
       determine whether a HI bit was pushed out of the data word during
       data rotation with the ROL and ROR instructions.
       Before you move on the instruction vocabulary of the MC68000,we'd
       like to give you another tip:
       The AssemPro assembler makes it quite easy to try every command in
       posible situations.Take the CMP command which we've been talking
       about,for example.To test this command with various values and to
       receive the results of the comparisons directly via the flags,try
       the following.
       Type the following into the Editor.
           run:
           cmp  $10,d1
           bra run
           end
       Assemble it,save the resulting code and enter the debugger.After
       reloading the code you can then single step through the program
       observing the results the program has on the flags.Try changing
       the values in the register D1 and see how higher and lower values
       affect the flag.
       By the way,using the start command at this time causes it to run 
       forever.Well,at least until reset is hit,which isn't exactly
       desirable,either...
       This procedure isn't limited to just the CMP instruction.You can
       use it to try any other instructions you're interested in.
     2.4.The 68000 Instructions.
     --------------------------
       Its about time to explain the MC68000 instructions.You don't have
       room for an in-depth discussion of each instruction in this book;
       for that purpose we recommend PROGRAMMING THE 68000 from Sybex by
       Steve Williams.
       The following tables show the required parameters and arguments
       for each instruction.AssemPro have access to built in help tables
       covering effective addressing modes and many of the Amiga
       Intuition calls.The following notation is used for arguments:
          Label     a label or address
          Reg       register
          An        address register n
          Dn        data register n
          Source    source operand
          Dest      destination operand
          <ea>      address or register
          #n        direct value
       Here is a short list of the instructions for the MC68000 processor
       AssemPro owners can simply place the cursor at the beginning of
       the instruction and press the help key to see the addressing modes
       allowed:
       Mnemonic             Meaning
       ---------------------------------------------------
      Bcc     Label         conditional branch,depends on condition
      BRA     Label         unconditional branch(similar to JMP)
      BSR     Label         branch to subprogram.Return address is
                            deposited on stack,RTS causes return to that
                            address.
      CHK     <ea>,Dx       check data register for limits,activate the
                            CHK instruction exception.
      DBcc    Reg,Label     check condition,decrement and branch
      JMP     Label         jump to address(similar to BRA)
      JSR     Label         jump to subroutine.Return address is
                            deposited on stack,RTS causes return to that
                            address.
      NOP                   no operation
      RESET                 reset peripherals(caution!)
      RTE                   return from exception
      RTR                   return with loading of flags
      RTS                   return from subroutine(after BSR and JSR)
      Scc     <ea>          set a byte to -1 when condition is met
      STOP                  stop processing(caution!)
      TRAP #n               jump to an exception
      TRAPV                 check overflow flag,the TRAPV exception
       Here are a few important notes...
       When a program jumps(JSR)or branches(BSR)to subroutine,the return
       address to which the program is to return is placed on the stack.
       At the RTS instruction,the address is pulled back off the stack,
       and the program jumps to that point.
       Lets experiment a little with this procedure.Please enter the 
       following short program:
         run:
                pea     subprogram   ;address on the stack
                jsr     subprogram   ;subprogram called
                move.l  (sp)+,d1     ;get a long word from stack
         ;      illegal              ;for assemblers without
                                     ;debuggers
         subprogram:
                move.l  (sp),d0      ;return address in D0
                rts                  ;and return
                end
       The first instruction,PEA,places the address of the subprogram on
       the stack.Next,the JSR instruction jumps to the subprogram.The
       return address,or the address at which the main program is to
       continue after the completion of the subprogram,is also deposited
       on the stack at this point.
       In the subprogram,the long word pointed to by the stack pointer is
       now loaded into the data register D0.After that,the RTS
       instruction pulls the return address from the stack,and the
       program jumps to that address.
       Back in the main program,the long word which is on the top of the
       stack,is pulled from the stack and written in D1.Assemblers that
       do not have the debugging features of AssemPro may need the
       ILLEGAL instruction so they can break the program and allow you to
       view the register contents.
       Assemble the program and load the resulting code into the debugger
       Single step thru the program and examine the register contents.
       Here you can see that D0 contains the address at which the program
       is to continue after the RTS command.Also,D1 contains the address
       of the subprogram which you can verify by comparing the debugger
       listing.
       The STOP and RESET instructions are so powerful that they can only
       be used in supervisor mode.Even if you do switch to the supervisor
       mode,you should NOT use these instructions if there is any data in
       memory that has not been saved and you wish to retain.
       The TRAP instruction receives a number between 0 and $F,which
       determines the particular TRAP vector(addresses $0080-$00BF)and
       thus the corresponding exception routine.Several operating systems
       for the 68000 utilize this instruction to call operating system
       functions.You'll deal more with this instruction later.
       In the short sample program that compared two numbers,the CMP
       instruction performed an arithmetic function,namely a subtraction.
       This subtraction could be performed with an actual result as well
       using the SUB instruction.The counterpart to this is in addition,
       for which the ADD instruction is used.In 8 bit processors,like the
       6502,these arithmetic functions are the only mathematical
       operations.The MC68000 can also multiply,divide,and perform these
       operations with a variety of data sizes.
       Most of the functions require two parameters.For instance the ADD
       instruction...
           ADD source,destination
       where source and destination can be registers or memory addresses.
       Source can also be a direct value(#n).The result of the opoeration
       is placed in the destination register or the destination address.
       This is same for all operation of this type.These instructions can
       be tried out with the AssemPro assembler.In this case we recommend
       the use of a register as the destination.
       Heres an overview of the arithmetic operations with whole numbers:
       Mnemonic                   Meaning
       --------------------------------------------------------------
       ADD       source,dest      binary addition
       ADDA      source,An        binary addition to a address register
       ADDI      #n,<ea>          addition with a constant
       ADDQ      #n,<ea>          fast addition of a constant which can
                                  be only from 1-8
       ADDX      source,dest      addition with transfer in X flag
       CLR       <ea>             clear an operand
       CMP       source,dest      comparison of two operands
       CMPA      <ea>,An          comparison with an address register
       CMPI      #n,<ea>          comparison with a constant
       CMPM      source,dest      comparison of two memory operands
       DIVS      source,dest      sign-true division of a 32 bit
                                  destination by a 16 bit source operand.
                                  The result of the division is stored in
                                  the LO word of the destination,the
                                  remainder in the HI word.
       DIVU      source,dest      division without regard to sign,similar
                                  to DIVS
       EXT       Dn               sign-true expansion to twice original
                                  size(width)data unit
       MULS      source,dest      sign-true multiplication of two words
                                  into one long word
       MULU      source,dest      multiplication without regard to sign,
                                  similar to MULS
       NEG       <ea>             negation of an operand(twos complement)
       NEGX      <ea>             negation of an operand with transfer
       SUB       source,dest      binary subtraction
       SUBA      <ea>,An          binary subtraction from an address
                                  register
       SUBI      #n,<ea>          subtraction of a constant
       SUBQ      #n,<ea>          fast subtraction of a 3 bit constant
       SUBX      source,dest      subtraction with transfer in X flag
       TST       <ea>             test an operand and set N and Z flag
       For the processing of whole numbers,the processor can operate with
       BCD numbers.These are Binary Coded Decimal numbers,which means
       that the processor is working with decimals.In this method,each
       halfbyte contains only numbers from 0 to 9,so that these numbers
       can be easily processed.For this method,the following instructions
       are available:
       Mnemonic                   Meaning
       -----------------------------------------------------------------
       ABCD      source,dest      addition of two BCD numbers
       NBCD      source,dest      negation of a BCD number(nine
                                  complement)
       SBCD      source,dest      subtraction of two BCD numbers
       Again,we recommend that you try this out yourself.Although
       handling the BCD numbers is relatively easy,it can be rather
       awkward at first.Be sure that you enter only BCD numbers for
       source and destination,since the results are not correct
       otherwise.
       Next are the logical operations,which you might know from BASIC.
       With these functions,you can operate on binary numbers bit for
       bit.
       Mnemonic                   Meaning
       -----------------------------------------------------------------
       AND       source,dest      logic AND
       ANDI      #n,<ea>          logic AND with a constant
       EOR       source,dest      exclusive OR
       EORI      #n,<ea>          exclusive OR with a constant
       NOT       <ea>             inversion of an operand
       OR        source,dest      logic OR
       ORI       #n,<ea>          logic OR wuth a constant
       TAS       <ea>             check a byte and set bit 7
       Single bits can also be manipulated by the following set of
       instructions:
       Mnemonic                   Meaning
       ----------------------------------------------------------------
       BCHG      #n,<ea>          change bit n(0 is changed to 1 and vice
                                  versa)
       BCLR      #n,<ea>          clear bit n
       BSET      #n,<ea>          set bit n
       BTST      #n,<ea>          test bit n,result is displayed in Z
                                  flag
       These instructions are particularly important from the
       manipulation and evaluation of data from peripherals.After all,in
       this type of data,single bits are often very significant.You'll
       come across this more in later chapters.
       The processor can also shift and rotate an operand within itself
       ('n'indicates a register,'#'indicates a direct value which
       specifies the number of shiftings)...
       Mnemonic                   Meaning
       ----------------------------------------------------------------
       AS        n,<ea>           arithmetic shift to the left(*2^n)
       ASR       n,<ea>           arithmetic shift to the right(/2^n)
       LSL       n,<ea>           logic shift to the left
       LSR       n,<ea>           logic shift to the right
       ROL       n,<ea>           rotation left
       ROR       n,<ea>           rotation right
       ROXL      n,<ea>           rotation left with transfer in X flag
       ROXR      n,<ea>           rotation right with transfer in X flag
       All these instructions allow you to shift a byte,a word or a long
       word to the left or right.Its not too surprising that this is the
       equivalentof multipling(dividing)the number by a power of 2.Here's
       a little example to demonstrate why
       Lets take a byte containing the value 16 as an example.In binary,
       it looks like this:
           %00010000 =16
       
       Now,if you shift the byte to the left by inserting a 0 at the
       right,you'll get the following result...
           %00010000 shifted to the left equals
           %00100000 =32,in effect 16*2
       Repeated shifting results in repeated doubling of the number.Thus
       if you shift the number n times,the number is multiplied by 2^n.
       The same goes for shifting to the right.However,this operation as
       a slight quirk:here's a sample byte with the value 5:
           %00000101 =5,shifted once to the right equals
           %00000010 =2
       The answer in this case is not 2.5 as you might expect.The result
       such a division is always a whole number,since any decimal places
       are discarded.If you use the DIV instruction instead of shifting,
       you'll retain the digits to the right of the decimal point.However
       shifting is somewhat faster,and shifting can also receive long
       words as results.
       After explaining the principle of shifting,you still need to know
       why more than two instructions are required for the procedure.Well
       this is because there are several different types of shifting.
       First,you must differentiate between shifting and rotating.In
       shifting,the bit that is added to the left or the right side is
       always a zero.In rotating,it is always a specific value that is
       inserted.This means that with the ROR or the ROL instructions,the
       bit that is taken out on one side is the one that is inserted on
       the other.With the ROXR and the ROXL instructions this bit takes a
       slight detour to the X flag.Thus,the content of the flag is
       inserted into the new bit,while the old bit is loaded into the 
       flag.
       Shifting as well,has two variations:arithmetic and logical
       shifting.You've already dealt with logical shifting.In this
       variation,the inserted bit is always a zero,and the extracted bit
       is deposited in the C flag and in the X flag.
       Although the highest bit,which always represents the sign,is
       shifted in arithmetic shifting,the sign is still retained by ASR.
       This has the advantage that when these instructions are used for
       division,the operation retains the correct sign(-10/2 equals-5).
       However,should an overflow or underflow cause the sign to change,
       this change is noted in the V flag,which always indicates a change
       in sign.With logical shifting this flag is always cleared.
       Now to the instructions that allow you to move data.These are
       actually the most important instructions for any processor,for how
       else could you process data?
       Mnemonic                   Meaning
       ------------------------------------------------------------------
       EXG       Rn,Rn            exchange of two register contents(don't
                                  confuse with swap)
       LEA       <ea>,An          load an effective address in address
                                  register An
       LINK      An,#n            build stack range
       MOVE      source,dest      carry value over from source to dest
       MOVE      SR,<ea>          transfer the status register contents
       MOVE      <ea>,SR          transfer the status register contents
       MOVE      <ea>,CCR         load flags
       MOVE      USP,<ea>         transfer the user stack point
       MOVE      <ea>,USP         transfer the user stack point
       MOVEA     <ea>,An          transfer a value to the address
                                  register An
       MOVEM     Regs,<ea>        transfer several registers at once
       MOVEM     <ea>,Regs        transfer several registers at once
       MOVEP     source,dest      transfer data to peripherals
       MOVEQ     #n,Dn            quickly transfer a 8 bit constant to
                                  the data register Dn
       PEA       <ea>             deposit an address on the stack
       SWAP      Dn               swap the halves of the register(the
                                  upper 16 bits with the lower)
       UNLK      An               unlink the stack
       The LEA or PEA instructions are often used to deposit addresses in
       an address register or on the stack.The instruction
            LEA   label,A0
       loads the address of the label'label' into the address register
       A0.In practice,this corresponds to
            MOVE.L  #label,A0
       which is equivalent to
            PEA  label
       All these instructions deposit the address of 'label' on the stack
       The following instruction also does this:
            MOVE.L  #label,-(SP)
       The LEA instruction becomes much more interesting when the label
       is replaced by indirect addressing.Here's an example:
            LEA   1(A0,D0),A1
       The address that's produced by the addition of 1(direct value
       offset)+A0+D0 is located in A1.To duplicate this instruction with
       MOVE would be quite cumbersome.Take a look:
            MOVE.L  A0,A1
            ADD.L   D0,A1
            ADDQ.L  #1,A1
       As you can see,the LEA instruction offers you quite some
       interesting possibilities.
       Those are all the instructions of the MC68000.Through their
       combination using the diverse methods of addressing,you can create
       a great number of different instructions,in order to make a
       program as efficent as possible.
       The following table is an overview of all MC68000 instructions
       along with their possible addressing types and the influence of
       flags.The following abbreviations are used:
           x=legal          s=source only    d=destination only
           -=not effected   0=cleared        *=modified accordingly
           1=set            u=undermined     P=privileged
       Mnemonic     1  2  3  4  5  6  7  8  9 10 11 12  X N Z V C   P
       -----------------------------------------------------------------
       ABCD         x
       ADD          s  s  x  x  x  x  x  x  x  s  s  s  * * * * *
       ADDA         x  x  x  x  x  x  x  x  x  x  x  x  - - - - -
       ADDI         x     x  x  x  x  x  x  x           * * * * *
       ADDQ         x  x  x  x  x  x  x  x  x           * * * * *
       ADDX         x           x                       * * * * *
       AND          s     x  x  x  x  x  x  x  s  s  s  - * * 0 0
       ANDI         x     x  x  x  x  x  x  x           - * * 0 0
       ASL, ASR     x     x  x  x  x  x  x  x           * * * * *
       Bcc                                              - - - - -
       BCHG         x     x  x  x  x  x  x  x           - - * - -
       BCLR         x     x  x  x  x  x  x  x           - - * - -
       BRA                                              - - - - -
       BSET         x     x  x  x  x  x  x  x           - - * - - 
       BSR                                              - - - - -
       BTST         x     x  x  x  x  x  x  x  z  x  x  - - * - - 
       CHK          x     x  x  x  x  x  x  x  x  x  x  - * u u u
       CLR          x     x  x  x  x  x  x  x           - 0 1 0 0
       CMP          x  x  x  x  x  x  x  x  x  x  x  x  - * * * *
       CMPA         x  x  x  x  x  x  x  x  x  x  x  x  - * * * * 
       CMPI         x     x  x  x  x  x  x  x           - * * * *
       CMPM               x        x  x  x  x     x  x  - * * *
       cpGEN                                            - - - - -
       DBcc                                             - - - - -
       DIVS         x     x  x  x  x  x  x  x  x  x  x  - * * * 0
       DIVU         x     x  x  x  x  x  x  x  x  x  x  - * * * 0
       EOR          x     x  x  x  x  x  x  x           - * * 0 0
       EORI         x     x  x  x  x  x  x  x           - * * 0 0
       EORI CCR                                         * * * * *
       EORI SR                                          * * * * *
       EXG                                              - - - - -
       EXT                                              - * * 0 0
       EXTB                                             - * * 0 0
       ILLEGAL                                          - - - - -
       JMP                x        x  x  x  x     x  x  - - - - -
       JSR                x        x  x  x  x     x  x  - - - - -
       LEA                x        x  x  x  x     x  x  - - - - -
       LINK            x                                - - - - -
       LSL, LSR           x  x  x  x  x  x  x           * * * 0 *
       MOVE         x  s  x  x  x  x  x  x  x  s  s  s  - * * 0 0
       MOVEA        x  x  x  x  x  x  x  x  x  x  x  x  - - - - -
       MOVE to CCR  x     x  x  x  x  x  x  x  x  x  x  * * * * *
       MOVE from SR x     x  x  x  x  x  x  x           - - - - -   P
       MOVE to SR   x     x  x  x  x  x  x  x  x  x  x  * * * * *   P
       MOVE USP        x                                - - - - -   P
       MOVEM              x  s  d  x  x  x  x     s  s  - - - - -
       MOVEP        s  d                                - - - - -
       MOVEQ        d                                   - * * 0 0
       MULS         x     x  x  x  x  x  x  x  x  x  x  - * * 0 0
       MULU         x     x  x  x  x  x  x  x  x  x  x  - * * 0 0
       NBCD         x     x  x  x  x  x  x  x           * u * u *
       NEG          x     x  x  x  x  x  x  x           * * * * *
       NEGX         x     x  x  x  x  x  x  x           * * * * * 
       NOP                                              - - - - -
       NOT          x     x  x  x  x  x  x  x           - * * 0 0
       OR           s     x  x  x  x  x  x  x  s  s  s  - * * 0 0
       ORI          x     x  x  x  x  x  x  x           - * * 0 0
       PEA                x        x  x  x  x     x  x  - - - - -
       RESET                                            - - - - -   P
       ROL, ROR           x  x  x  x  x  x  x           - * * 0 *
       ROXL, ROXR         x  x  x  x  x  x  x           - * * 0 *
       RTE                                              - - - - -   P
       RTR                                              * * * * *
       RTS                                              - - - - - 
       SBCD         x           x                       * u * u *
       Scc          x     x  x  x  x  x  x  x           - - - - -
       STOP                                    x        - - - - -
       SUB          s  s  x  x  x  x  x  x  x  s  s  s  * * * * *
       SUBA         x  x  x  x  x  x  x  x  x  x  x  x  - - - - -
       SUBI         x     x  x  x  x  x  x  x           * * * * *
       SUBQ         x  x  x  x  x  x  x  x  x           * * * * *
       SUBX         x           x                       * * * * *
       SWAP         x                                   - * * 0 0
       TAS          x     x  x  x  x  x  x  x           - * * 0 0
       TRAP                                    x        - - - - -
       TRAPV                                            - - - - -
       TST          x     x  x  x  x  x  x  x           - * * 0 0
       UNLK            x                                - - - - -
Személyes eszközök