Third Steps =========== Multiplication -------------- The 68000 only permits word by word multiplication. The result is always a long word. Both signed and unsigned multiplication are caterd for. Up until now we have only considerd +ve numbers when dealing with arithmetic so I will now give a very brief discription of how signed numbers are stored. Firstly the most signifigant bit of the byte, word or long word is used as a sign bit. If this bit is 0 then the value is treated as positive. Here are some byte examples: %01001101 = +77 or just 77 %00000101 = +5 or just 5 %01011101 = +93 or just 93 If the MSB is 1 then the value is treated as negative and things become a little more complicated. Negative numbers are stored in what is known as twos compliment notation. This is a fancy way of saying 'change all 1's to 0's and all 0's to 1's then add 1 onto the result'. I will explain the use of 2's complement shortly, for now lets look at a couple of examples: 77 = %01001101 change all 1's to 0's and all 0's to 1's : %10110010 and now add 1 : %10110010 + % 1 ---------- %10110011 So %10110011 = -77 Just to make sure you have got the hang of things out the 2's complement form of -5 and -93. Here are the answers for you to check your results with: -5 = %11111011 -93 = %10100011 Incedentaly these values can be converted to hex and still be used. ie. -5 + %11111011 = $f6 Now you know how signed numbers are stored lets look at multiplication. MULU ---- Syntax : Mulu.w ,Dn Unsigned multiplication. Both source and destination are word values. The result is a long word and is stored in the destination which is always a data register. Here is an example: ; eg_11.s main move.w value1,d0 mulu.w value2,d0 move.l d0,result display_d0 rts value1 dc.w 5 value2 dc.w 4 result dc.l 0 As you would expect the result is 20. MULS ---- Syntax : Muls.w ,Dn Signed multiplication. Treat the same as MULU except source and destination are treated as signed numbers. To demonstrate lets multiply -5 by -4, the result should be 20. ; eg_12.s main move.w value1,d0 muls.w value2,d0 move.l d0,result display_d0 rts value1 dc.w -5 value2 dc.w -4 result dc.l 0 Lets try another using signed arithmetic. 2 x (-3) + 8 = 2, agree ? Well here is the program to try it out. ; eg_13.s main move.w #2,d0 muls.w #-3,d0 add.w #8,d0 display_d0 rts Hopefully the last two examples have convinced you that the Amiga can deal with signed integer arithmetic. Division -------- The 68000 will only allow long word values to be divided by word values. The result is stored in the destination in two parts. The first word of the result is the remainder and the second word is the quotient. This is necessary as only integer values can be dealt with. Take for instance the following examples: 3 / 2 = 1 remainder 1 7 / 3 = 2 remainder 1 384 / 7 = 54 remainder 6 Division by zero will cause a processor trap to occur and you will be visited by the infamous Guru. You have been warned ! Divu ---- Syntax : Divu.w ,Dn Unsigned division. The destination is divided by the source and the result is stored in the destination. ie. destination = destination / source As mentioned above the source operand must be of word length and the destination must be of long word length. The long word result will be stored in the destination which must always be a data register. eg. 16 / 4 = 4 ; eg_14.s main moveq.l #16,d0 divu.w #4,d0 display_d0 rts Or from memory: ; eg_15.s main move.l value1,d0 divu.w value2,d0 move.l d0,result display_d0 rts value1 dc.l 16 value2 dc.w 4 result dc.l 0 This is all ok since there is no remainder. What happens if the division does not yield an exact integer result, say 17 / 7 ; eg_16.s main moveq.l #17,d0 divu.w #7,d0 display_d0 rts On running this you will see that the result is 2, the quotient. How do we move the remainder into the least signifigant word of d0 so we can manipulate it ? Enter our next instruction: SWAP ---- Syntax : Swap dn This instruction swaps the least and most signifigant words of a data register around. eg. if d0 = $00010002 then MSW=$0001 LSW=$0002 after swap d0 : d0 = $00020001 ie MSW=$0002 LSW=$0001 { MSW = Most Signifigant Word, LSW = Least Signifigant Word } Now we can view the complete result of dividing 17 by 7: ; eg_17.s main moveq.l #17,d0 divu.w #7,d0 display_d0 swap d0 display_d0 rts The result is 2 remainder 3 { ( 2 x 7 ) + 3 = 17 }. DIVS ---- Syntax : Divs.w ,Dn Signed divide. Operates the same as Divu except source and destination are treated as signed numbers. Arithmetic Examples =================== Nothing to flash here, just a couple of examples to get you going. 1. Area of a circle ------------------- As we all know ( I hope ) the area of a circle is calulated using the formula Area = PI x ( Radius )² Well for the purpose of this example lets use the approximation: PI = 22 / 7 ( 3.143 ) So we could rewrite the formula as : Area = 22 x Radius x Radius / 7 We will have to live with the result being accurate to the nearest whole number for now, but here is the source: ; eg_18.s main move.w radius,d0 mulu.w d0,d0 mulu.w #22,d0 divu.w #7,d0 display_d0 rts radius dc.w 4 As you would expect the answer given is 50 ( PI x 4² = 50.27 ). 2. VAT man ---------- This program totals the amount of VAT you would have to pay on the five items stored in the price list. VAT is 15% so we first multiply by 15 and then divide by 100. This result is added to a running total. ; eg_19.s main move.l price_list,a0 a0-->the price list moveq.l #0,d1 clear the total move.w (a0)+,d0 get price of article mulu.w #15,d0 calculate VAT divu.w #100,d0 add.w d0,d1 add to total move.w (a0)+,d0 get price of article mulu.w #15,d0 calculate VAT divu.w #100,d0 add.w d0,d1 add to total move.w (a0)+,d0 get price of article mulu.w #15,d0 calculate VAT divu.w #100,d0 add.w d0,d1 add to total move.w (a0)+,d0 get price of article mulu.w #15,d0 calculate VAT divu.w #100,d0 add.w d0,d1 add to total move.w (a0)+,d0 get price of article mulu.w #15,d0 calculate VAT divu.w #100,d0 add.w d0,d1 add to total display_d1 rts price_list dc.w 23 dc.w 15 dc.w 145 dc.w 73 dc.w 45 As you will see in the above program the sequence: move.w (a0)+,d0 get price of article mulu.w #15,d0 calculate VAT divu.w #100,d0 add.w d0,d1 add to total is repeated five times. What would happen if we had 1000 articles in our list. We would end up with a bloody big program ! To get around this problem it is possible to use loops. A set of instructions are available for repeating a section of code over and over. That's what we are going to look at next. LOOPS ===== Almost all instructions have some effect on the internal flags. These flags are set according to the result of the operation preformed. For example moveq.l #0,d0 would cause the Z flag to be set since the result of this operation is zero. Here is a list of the various flags along with a brief explanation of each: X Extend flag set same as carry flag N Negative flag set if MSB of result is negative,cleared otherwise Z Zero flag set if result is zero,cleared otherwise V Overflow Flag set if arithmetic overflow occurs,cleared otherwise C Carry flag set if carry is generated,cleared otherwise Action can be taken according to the condition of one or more the above flags. For example if the Z flag is set do one thing, else do another. This is the basis of looping in assembly language. Condition Codes --------------- The condition codes test the state of various combinations of the internal. The result of this test is either true or false. This result can be utalised in the branch instruction Bcc. If the condition code specified is true then the branch will take place, else the branch is ignored and execution will continue at the instruction following the branch. Here are the various condition codes available for use, do not worry to much about the right most colomn for now. cc Condition Bits ------------------------------------------------------ T true always,corresponds to BRA F false always,never bvranches HI higher than C'*Z' LS lower or same C+Z HS,CC higher or same,carry clear C' LO,CS lower,carry clear C NE not equal (non zero result) Z' EQ equal (zero result) Z VC overflow clear V' VS overflow set V PL posotive result MI negative result 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 than or equal Z + N*V' + N'*V { Boolean operators: *=AND +=OR '=NOT } Now lets see how to implement these test and branch instructions. Bcc --- Syntax : Bcc