PDA

View Full Version : 32 bit math



Charles Linquis
- 25th August 2006, 18:57
I am writing an SNMP parser. The TRAP command requires that I show elapsed time in 'timer ticks', which are defined as 10mSec in length. I have talked my customer into accepting 1 Second updates, and I have written a 32 bit seconds counting routine (using 2-16 bit words). But now, to get timer ticks, I have to multiply this 32 bit number (actually only 25 bits will be used) by 100.

Can someone tell me how I might do this?

BigWumpus
- 25th August 2006, 20:12
Oh,

it is easy !

Shift left all bits by 2 positions (= x4),
store it to a variable X
Shift left all bits by 3 positions (= x32),
add it to the variable X
Shift left all bits by 1 position (= x64),
add it to the variable X

X is holding the result !

It can easily be done by small assembler-code.

Charles Linquis
- 25th August 2006, 20:39
Unfortunately, I'm "assembly challenged" when it comes to math. Can someone point me to a good source of information on how to accomplish what Mr. Wumpus has explained?

BigWumpus
- 25th August 2006, 21:10
IMHO:

;Here you must place your 32-bit-value
AU var byte BankA ;Upper
AH var byte BankA ;High
AM var byte BankA ;Middle
AL var byte BankA ;low

;Here the result is placed
XU var byte BankA ;Upper
XH var byte BankA ;High
XM var byte BankA ;Middle
XL var byte BankA ;low

asm
;clear X
clrf _XU
clrf _XH
clrf _XM
clrf _XL
;shift A by 1 position left
rlncf _AL,f
rlcf _AM,f
rlcf _AH,f
rlcf _AU,f
[repeat the shift-routine]
;move A to X
movff _AU,_XU
movff _AH,_XH
movff _AM,_XM
movff _AL,_XL
[repeat the shift-routine]
[repeat the shift-routine]
[repeat the shift-routine]
;add A to X
movf _AL,w
addwf _XL,f ;ignore Carry
movf _AM,w
addwfc _XM,w
movf _AH,w
addwfc _XH,w
movf _AU,w
addwfc _XU,w
[repeat the shift-routine]
[repeat the add-routine]
endasm

Charles Linquis
- 25th August 2006, 22:52
Thanks for the code, but when I input 0x64, I get 0x90 as an output.

In the meantime, I try to figure it out at this end.

Charles Linquis
- 25th August 2006, 23:16
This is what I'm using.

If input = $64
Output = $36

;-----------------------------------------------------------------

The code:


Mult32:

asm
;clear X
clrf _XU
clrf _XH
clrf _XM
clrf _XL

;shift A by 1 position left

rlncf _AL,f
rlcf _AM,f
rlcf _AH,f
rlcf _AU,f

;[repeat the shift-routine]

rlncf _AL,f
rlcf _AM,f
rlcf _AH,f
rlcf _AU,f


;move A to X

movff _AU,_XU
movff _AH,_XH
movff _AM,_XM
movff _AL,_XL

;[repeat the shift-routine]

rlncf _AL,f
rlcf _AM,f
rlcf _AH,f
rlcf _AU,f

;[repeat the shift-routine]

rlncf _AL,f
rlcf _AM,f
rlcf _AH,f
rlcf _AU,f

;[repeat the shift-routine]

rlncf _AL,f
rlcf _AM,f
rlcf _AH,f
rlcf _AU,f


;add A to X

movf _AL,w
addwf _XL,f ;ignore Carry
movf _AM,w
addwfc _XM,w
movf _AH,w
addwfc _XH,w
movf _AU,w
addwfc _XU,w

;[repeat the shift-routine]

rlncf _AL,f
rlcf _AM,f
rlcf _AH,f
rlcf _AU,f

;[repeat the add-routine]

movf _AL,w
addwf _XL,f ;ignore Carry
movf _AM,w
addwfc _XM,w
movf _AH,w
addwfc _XH,w
movf _AU,w
addwfc _XU,w



endasm

Darrel Taylor
- 26th August 2006, 20:02
Charles,

You have a timer running at 100 hz, and you're dividing those interrupts by 100 to count seconds. Then later you want to multiply the seconds times 100.

Why not just count the interrupts directly? Then you have the Sec*100 already (plus fractional secs), and you can DIV32 100 that number for the seconds, or keep a separate count for the seconds and no DIV or MUL required.
<br>

Charles Linquis
- 26th August 2006, 22:06
Darrel,

Actually, I have 1Khz interrupt running. I really didn't want to use it because I really like routines that run often to be very short. Since this is for an SNMP trap (an ERROR has ocurred), the timer tick value will be output something like once a year. That is why I wanted to do the multiply only when necessary.

Maybe I'm getting too stingy with the 8722's time!

Darrel Taylor
- 27th August 2006, 08:27
OK, that sounds reasonable enough.

So back to BigWumpus' code.

The rlncf's are a problem because it rotates the high bit around to the low bit. What needs to be done is rotate a 0 into the Low bit, and the High bit to the carry.

bcf STATUS, C
rlcf _AL,f
rlcf _AM,f
rlcf _AH,f
rlcf _AU,f

and the addwfc's need to go to F (file) instead of W. Here's the corrected code...
asm

;clear X
clrf _XU
clrf _XH
clrf _XM
clrf _XL

;shift A by 1 position left
bcf STATUS, C
rlcf _AL,f
rlcf _AM,f
rlcf _AH,f
rlcf _AU,f

;[repeat the shift-routine]

bcf STATUS, C
rlcf _AL,f
rlcf _AM,f
rlcf _AH,f
rlcf _AU,f


;move A to X

movff _AU,_XU
movff _AH,_XH
movff _AM,_XM
movff _AL,_XL

;[repeat the shift-routine]

bcf STATUS, C
rlcf _AL,f
rlcf _AM,f
rlcf _AH,f
rlcf _AU,f

;[repeat the shift-routine]

bcf STATUS, C
rlcf _AL,f
rlcf _AM,f
rlcf _AH,f
rlcf _AU,f

;[repeat the shift-routine]

bcf STATUS, C
rlcf _AL,f
rlcf _AM,f
rlcf _AH,f
rlcf _AU,f


;add A to X

bcf STATUS, C
movf _AL,w
addwfc _XL,f
movf _AM,w
addwfc _XM,F
movf _AH,w
addwfc _XH,F
movf _AU,w
addwfc _XU,F

;[repeat the shift-routine]

bcf STATUS, C
rlcf _AL,f
rlcf _AM,f
rlcf _AH,f
rlcf _AU,f

;[repeat the add-routine]

bcf STATUS, C
movf _AL,w
addwfc _XL,f
movf _AM,w
addwfc _XM,F
movf _AH,w
addwfc _XH,F
movf _AU,w
addwfc _XU,F
endasm


Or, Here's my little spin on it.

gosub Mult32

;______________________________
Mult32:
asm
call ShiftA
call ShiftA ; *4
movff _AU,_XU ; move A to X
movff _AH,_XH
movff _AM,_XM
movff _AL,_XL
call ShiftA
call ShiftA
call ShiftA ; *32
call AddAX ;add A to X
call ShiftA ; *64
call AddAX ;add A to X
return
;________________________________________________
ShiftA ; shift A by 1 position left
bcf STATUS, C
rlcf _AL,f
rlcf _AM,f
rlcf _AH,f
rlcf _AU,f
return

AddAX ; add A to X
movf _AL,w
addwf _XL,F ;ignore Carry
movf _AM,w
addwfc _XM,F
movf _AH,w
addwfc _XH,F
movf _AU,w
addwfc _XU,F
return
endasm


HTH,
&nbsp; DT

Charles Linquis
- 28th August 2006, 00:57
Thank you Darrel,

Your routine works as advertised. Now I can get on with the rest of the details of "SIMPLE" Network Management Protocol. HA!

Darrel Taylor
- 28th August 2006, 01:55
And I'll defer that to BigWumpus,

Great idea, just needed a little debugging.

DT

BigWumpus
- 28th August 2006, 07:23
OK,
look at the time of my message ... it was late !

Charles Linquis
- 28th August 2006, 13:34
Well thanks to you both, then!