Multiplication with a Micro-controller using the add and shift method

Thread Starter

James Harris 2

Joined Aug 22, 2017
7
This is the code that I have come up with at this point, but it does not seem work. I have been at this for hours I just do not see the problem, but I am new to this so it could be something simple. I am required to use the PIC16F887 thus i am limited to its' instruction set. The code is in Assembly also
I am attempting to use the add and shift method my code is below

cblock 0x020
multiplicand_low,multiplicand_high,product_low,product_high,multiplier,count
endc

org 0x00
Init
movlw .0
movwf product_low
movlw .0
movwf product_high
movlw .8
movwf count
goto Main



Main call Prob1



Prob1 movlw 0x9D
movwf multiplicand_low
movlw 0xA3
movwf multiplier
call Multiply

Multiply
rrf multiplier,F
btfsc status,C
call Add
rrf multiplicand_low,F
rrf multiplicand_low,F
decfsz count
return
goto $

Add
movf multiplicand_low,W
addwf product_low,F
btfsc status,C
incf product_high,F
movf multiplicand_high,W
addwf product_high,F
return
 
Last edited:

WBahn

Joined Mar 31, 2012
32,823
Identify the smallest numbers that produce incorrect results.

Then walk through it by hand. You want to see if (1) you get the same number the program produced when it ran, and (2) at what point the values that you actually see deviate from what you expect to see.
 

absf

Joined Dec 29, 2010
1,968
I am putting in code tags so it would be easier for others to help you...

Code:
cblock 0x020
multiplicand_low  ;lower byte of multiplicand
multiplicand_high ;upper byte of multiplicand
product_low          ;lower byte of product
product_high         ;upper byte of product
multiplier
count              ;number of times of repeat      
endc

org 0x00
Init
movlw .0
movwf product_low
movlw .0
movwf product_high
movlw .8
movwf count
goto Main



Main call Prob1



Prob1 movlw 0x9D
movwf multiplicand_low
movlw 0xA3
movwf multiplier
call Multiply

Multiply
rrf multiplier,F
btfsc status,C
call Add
rrf multiplicand_low,F             ;why 2 same instructions here ?
rrf multiplicand_low,F             ;are you sure it should be rrf ?
decfsz count
return
goto $

Add
movf multiplicand_low,W
addwf product_low,F
btfsc status,C
incf product_high,F
movf multiplicand_high,W
addwf product_high,F
return
You should also put plenty of comments after each instructions so you know what each line was doing. This would prevent you from losing track of your program.

Try to study the mechanics of the "call" instruction, what do the program do after each sub-routine is finished, where does the program counter points to after "return" instruction ?

You also forgot to clear the multiplicand_high at the beginning of the program.

Allen
 
Last edited:

Thread Starter

James Harris 2

Joined Aug 22, 2017
7
I am putting in code tags so it would be easier for others to help you...

Code:
cblock 0x020
multiplicand_low  ;lower byte of multiplicand
multiplicand_high ;upper byte of multiplicand
product_low          ;lower byte of product
product_high         ;upper byte of product
multiplier
count              ;number of times of repeat    
endc

org 0x00
Init
movlw .0
movwf product_low
movlw .0
movwf product_high
movlw .8
movwf count
goto Main



Main call Prob1



Prob1 movlw 0x9D
movwf multiplicand_low
movlw 0xA3
movwf multiplier
call Multiply

Multiply
rrf multiplier,F
btfsc status,C
call Add
rrf multiplicand_low,F             ;why 2 same instructions here ?
rrf multiplicand_low,F             ;are you sure it should be rrf ?
decfsz count
return
goto $

Add
movf multiplicand_low,W
addwf product_low,F
btfsc status,C
incf product_high,F
movf multiplicand_high,W
addwf product_high,F
return
You should also put plenty of comments after each instructions so you know what each line was doing. This would prevent you from losing track of your program.

Try to study the mechanics of the "call" instruction, what do the program do after each sub-routine is finished, where does the program counter points to after "return" instruction ?

You also forgot to clear the multiplicand_high at the beginning of the program.

Allen
Code:
    #include    P16F887.inc
    #include    lowercase_887sfr.inc
          
; define constants
status            equ    0x003
C                   equ    0
Z                   equ    2
  
        cblock    0x020
        multiplicand_low,multiplicand_high,product_low,product_high,multiplier,count
        endc
      
        org    0x00
Init  
    movlw    .0
    movwf    product_low
    movlw    .0
    movwf    product_high
    movlw    .8
    movwf    count
    goto       Main

Main          call    Prob1
                  goto    $

Prob1    
                  movlw    0x9D
                  movwf    multiplicand_low
                  movlw    0xA3
                  movwf    multiplier
                  clrf    multiplicand_high
                  call    Multiply
                  return

Multiply
                  bcf        status,C      
                  rrf        multiplier,F
                  btfsc    status,C
                  call    Add
                  rlf        multiplicand_low,F
                  rlf        multiplicand_high,F
                  decfsz    count,F
                  goto    Multiply
                  return

Add        
                 movf    multiplicand_low,W
                 addwf    product_low,F
                 btfsc    status,C
                 incf    product_high,F
                 movf    multiplicand_high,W
                 addwf    product_high,F
                 return
                 end

Thanks for the help this is the new code minus the comments which I will be adding it seems to work now. Just by looking at this code would you happen to see any quick ways to reduce the code in Assembly Language.
 
Last edited:

absf

Joined Dec 29, 2010
1,968
Your program is a straight forward approach which mimic how I would do it using paper and pen.

There are more efficient algorithm which are faster and use less instructions. You can take a look at some of then here...

http://www.piclist.com/techref/microchip/math/mul/index.htm

Code:
; Enter with multiplier in W-Reg, multiplicand in "PRODLO".
; Exits with product in PRODHI:PRODLO.

    MPY8X8:

    CLRF PRODHI

    CLRF COUNT
    BSF COUNT,3    ;this instruction is same as "movlw 8,  movwf count"

    RRF PRODLO,F

    LOOP:

    SKPNC
    ADDWF PRODHI,F

    RRF PRODHI,F
    RRF PRODLO,F

    DECFSZ COUNT
    GOTO LOOP
This one uses only few instructions and the variable multiplicand shares with product_low.
courtesy from Andrew Warren. See if you can figure out how it works.;)

Allen
 
Last edited:
Top