fast 8x8bit multiplication assembly pic18

3.4k Views Asked by At

Im trying to multiply two 8 bit numbers and store them in a 16 bit location for results larger than 255. The fastest way to accomplish this is through shifting, which I have tried to implement via the rrcf function and using bcf to clear unwanted carries.

This is what ive came up with. Ive tried to comment all the code so you are able to see my thought process. Im fairly new to both the PIC18 and programming in ASM in general. Please keep that in mind when (hopefully) providing help. I need to get put in a better spot than I am in, when I run MPLAB SIM, all I get is the counter decrementing...?

I think this is due to the last bit of multiplier being repeatedly tested, which will be zeros and and therefore skip my add instruction every time. Can you help me create a loop to move BTFSC progressively from bit 0-7? I think this is the problem, but i can't figure out the code. I could essentailly write main 8 times, but im trying to save code space

            LIST P=18F4550
            #include <P18F4550.INC>

            ;equates
            counter equ 0x00 ;set counter
            multiplicand equ 0x01 ;set multiplicand
            multiplier equ 0x02 ;set multiplier
            resultHigh equ 0x03 ;set resultHigh
            resultLow equ 0x04 ;set resultLow

            ;test program

            movlw d'100' ;move literal d'100' to wreg
            movwf multiplicand ;set multiplicand
            movlw d'400'       ;move literal d'400'
            movlw multiplier   ;set multiplier
            movlw d'8'         ;counter
            movwf counter      ;set counter

            main:
            btfsc multiplier, 0          ;test LSB if 0,skip next if 0
            addwf multiplier, resultLow  ;add if 1 to resultLow
            bcf STATUS,C                 ;clear carry flag
            rlcf multiplier              ;rotate multiplier left
            bcf STATUS,C                 ;clear carry
            rlcf resultLow               ;rotate resultLow w/ carry
            rlcf resultHigh              ;rotate resultHigh 
                                                                  ;w/carry from resultLow

            decf counter                 ;dec counter
            goto main                    ;repeat for 8 bits
            end
2

There are 2 best solutions below

0
On

Actually the PIC18 asm support single CPU cycle 8*8 unsign hardware multiplication.

   MOVLW 100
   MOVWF multiplicand
   MOVLW 33
;multiply multiplicand with WREG 
   MULWF multiplicand
;product is stored in registers PRODH:PRODL
5
On

There are several odd things about this code:

  1. you never use multiplicand, so how can you possibly multiply by it? Was it a copy-and-paste error when you wrote addwf multiplier, resultLow? By all logic that's where multiplicand should be, unless you want to calculate a square of one number instead of a product of two numbers.

  2. you test the least significant bit of multiplier, which makes sense as you need to check its bits, but then you shift multiplier left, turning that bit into 0 forever. Doesn't seem right. Either you should do a right shift or check the most significant bit instead.

  3. the shift of the result occurs after the addition to it. Suppose, you are multiplying 1-bit numbers instead of 8-bit numbers, for example 1 by 1, and expecting 1 in the product. So, you add 1 to the result and then shift the result left. That alone gives you 2 in the product. How can that be right? How about reversing the order of the shift and the add?

  4. I can't see how the loop finishes when counter reaches 0. While I'm unfamiliar with your CPU, it looks to me that you decrement counter and then unconditionally jump back to main. What makes this a conditional jump?

The following pseudo code shows how multiplication should be done:

multiplier = multiplier_value
multiplicand = multiplicand_value

counter = 8
resultLow = 0
resultHigh = 0

main:

carry = 0
shift left: carry <- resultLow <- carry
shift left: carry <- resultHigh <- carry

carry = 0 ; you don't need to zero it here, actually
shift left: carry <- multiplier <- carry

if carry = 0, goto no_add

carry = 0
resultLow = resultLow + multiplicand + carry
resultHigh = resultHigh + 0 + carry

no_add:

counter = counter - 1
if counter ≠ 0, goto main