Many years ago DT helped me with something similar
https://www.picbasic.co.uk/forum/showthread.php/24-Retrieving-32bit-Multiply-Result
Not sure if it might apply to your application.
Nick
Many years ago DT helped me with something similar
https://www.picbasic.co.uk/forum/showthread.php/24-Retrieving-32bit-Multiply-Result
Not sure if it might apply to your application.
Nick
yes biggest num is 655359999Without really thinking I changed DIV32 to 10000 and massaged the display code but obviously it only pushes the problem to when the high word is >10000.
this does a divide by 100000 first in asm and will do rest in pbp to encompass the entire 32 bit signed range
Code:#config CONFIG RETEN=OFF CONFIG XINST = OFF ;Extended Instruction Set CONFIG FOSC = INTIO2 ;internal RC oscillator CONFIG SOSCSEL=DIG CONFIG FCMEN = OFF ;Fail-Safe Clock Monitor **** CONFIG IESO = OFF ;Two-Speed Start-up is disabled CONFIG PLLCFG = OFF ;4x xtal PLL CONFIG PWRTEN = ON ;Power-up Timer CONFIG BOREN = SBORDIS ; Brown-out Reset Enabled in hardware, SBOREN disabled CONFIG BORPWR = HIGH ;BOR MV set to high power level CONFIG BORV = 2 ; Brown-out Reset 0=3v, 1=2.7v, 2=2v, 3=1.8v CONFIG WDTEN = SWDTDIS ;ON ;OFF ;WDT enabled in hardware; SWDTEN bit disabled CONFIG WDTPS = 512 ;WDT 512*4Ms = 2 SECONDS CONFIG RTCOSC = INTOSCREF ; RTCC uses INTRC CONFIG MCLRE = ON CONFIG STVREN = ON ;Stack Full/Underflow Reset CONFIG DEBUG = OFF ;Background Debugger CONFIG CP0 = OFF ;code-protected CONFIG CP1 = OFF CONFIG CP2 = OFF CONFIG CP3 = OFF CONFIG CP4 = OFF CONFIG CP5 = OFF CONFIG CP6 = OFF CONFIG CP7 = OFF CONFIG CPB = OFF ;Boot Block Code Protection CONFIG CPD = OFF ;Data EEPROM Code Protection #endconfig DEFINE OSC 64 DEFINE DEBUG_REG PORTD DEFINE DEBUG_BIT 4 DEFINE DEBUG_BAUD 9600 DEFINE DEBUG_MODE 0 '0=TRUE 1=INVERTER OSCCON=110100 OSCTUNE.6=1 'Frequency Multiplier PLL Enable bit FOR INIT RC TRISD=$ed ANCON0=0 'AN0-AN7 digital port ANCON1=0 'AN8-AN15 digital port ANCON2=0 'AN16-AN23 dig PSPCON.4=0 'General Purpose I/O mode 'PSPMODE: Parallel Slave Port Mode Select bit Test var byte[3] SYSTEM Dividend var byte[6] SYSTEM Remainder var byte[4] SYSTEM ; remainder from 1000000 division Shift var byte[6] SYSTEM Counter VAR BYTE SYSTEM Hours VAR WORD[2] ; 32-bit (Dword) Holds up to 99999.9 hours HoursH VAR Hours(1) HoursL Var Hours(0) QUOTL VAR WORD EXT ; top 5 digits Result Var Word ; middle 10,000;s single digit Remains Var Word ; bottom 4 digits i var byte goto overasm Asm QUOTL=Dividend PutMulResult?D macro Din MOVE?BB Din, R2 MOVE?BB Din + 1 , R2 + 1 MOVE?BB Din + 2, R0 MOVE?BB Din + 3, R0 + 1 RST?RP endm PutDIV?D macro Din MOVE?BB Din, Dividend MOVE?BB Din + 1 , Dividend + 1 MOVE?BB Din + 2, Dividend + 2 MOVE?BB Din + 3, Dividend + 3 MOVE?CB 0 , Dividend + 4 MOVE?CB 0 , Dividend + 5 RST?RP endm EndAsm Remainder[3]=0 overasm: HoursL=$fff0 HoursH=$7fff latd=18 debug "ready",13,10 pause 1000 MainLoop: gosub AddHourTenth Gosub ShowHourMeter goto MainLoop ;============================================================ AddHourTenth: HoursL = HoursL + 1 IF HoursL = 0 then HoursH = HoursH + 1 return ShowHourMeter: Test [0]=$a0 ;divisor 100000 Test [1]=$86 Test [2]=1 @ PutDIV?D _Hours CALL Div4824U ;divide by 100000 debug ,13,10 @ PutMulResult?D Remainder Result = DIV32 10000 Remains = R2 debug DEC QUOTL, Dec1 Result, ".",DEC4 Remains ,13,10 pause 1000 return ;************************************************************************** ;Div4824U ;Inputs: ; Dividend - Dividend:6 (0 - least significant!) ; Divisor - Test:3 (0 - least significant!) ;Temporary: ; Counter - Count ; Shift - Shift:6 ;Output: ; Quotient - Dividend:6 (0 - least significant!) ; Remainder- Rem:3 (0 - least significant!) ; ;Adaptation of 24x24 division by Tony Nixon with corrections ;by Frank Finster 3/15/2005. ;Code adapted by Andy Lee ;01-Sep-2006 Original version ;************************************************************************** Div4824U: asm ;--------------------------------------------------- ; SUBROUTINE - 48 by 24 BIT DIVISION movlw 48 movwf Counter movff Dividend+0, Shift+0 movff Dividend+1, Shift+1 movff Dividend+2, Shift+2 movff Dividend+3, Shift+3 movff Dividend+4, Shift+4 movff Dividend+5, Shift+5 clrf Dividend+0 clrf Dividend+1 clrf Dividend+2 clrf Dividend+3 clrf Dividend+4 clrf Dividend+5 clrf Remainder+2 clrf Remainder+1 clrf Remainder+0 dloop bcf STATUS, C rlcf Shift+0 rlcf Shift+1 rlcf Shift+2 rlcf Shift+3 rlcf Shift+4 rlcf Shift+5 rlcf Remainder+0 rlcf Remainder+1 rlcf Remainder+2 movf Test+2, w subwf Remainder+2, w btfss STATUS, Z bra nochk movf Test+1,w subwf Remainder+1,w btfss STATUS, Z bra nochk movf Test+0,w subwf Remainder+0,w nochk btfss STATUS, C bra nogo movf Test+0,w subwf Remainder+0 btfsc STATUS, C bra nodec_remainM decf Remainder+1, f movf Remainder+1, w xorlw 0xff btfsc STATUS, Z decf Remainder+2, f nodec_remainM movf Test+1, w subwf Remainder+1, f btfss STATUS, C decf Remainder+2, f movf Test+2, w subwf Remainder+2, f bsf STATUS, C nogo rlcf Dividend+0 rlcf Dividend+1 rlcf Dividend+2 rlcf Dividend+3 rlcf Dividend+4 rlcf Dividend+5 decfsz Counter, f goto dloop return endasm
Warning I'm not a teacher
Thanks Nick,
As far as I can see the examples provided by Darrel in that thread has the same limitation as in "only" going to 655359999 which is "only" ~15% of the 32bit range.
In my case I really do need the full 32bits since the value can and do wrap around. Displaying it signed would be cool but I'll take unsigned over what I have right now any day.
Richard,
Wow, thank you very much indeed!
I have it running on a little dev.board, next is to incorporate it in the actual code, we'll see how that goes.
Thanks again!
/Henrik.
A few tweaks to scrounge some resources back
Code:Test var byte[3] SYSTEM Dividend var byte[6] SYSTEM Remainder var byte[3] SYSTEM ; 24 bit remainder from 1000000 division Shift var byte[6] SYSTEM Counter VAR BYTE SYSTEM Hours VAR WORD[2] ; 32-bit HoursH VAR Hours(1) HoursL Var Hours(0) QUOTL VAR WORD EXT ; top 5 digits Result Var Word ; middle 10,000;s single digit Remains Var Word ; bottom 4 digits i var byte goto overasm Asm QUOTL=Dividend PutMulResult?D macro Din MOVE?BB Din, R2 MOVE?BB Din + 1 , R2 + 1 MOVE?BB Din + 2, R0 MOVE?BB Din + 3, R0 + 1 RST?RP endm PutDIV?D macro Din MOVE?BB Din, Dividend MOVE?BB Din + 1 , Dividend + 1 MOVE?BB Din + 2, Dividend + 2 MOVE?BB Din + 3, Dividend + 3 MOVE?CB 0 , Dividend + 4 MOVE?CB 0 , Dividend + 5 RST?RP endm PutSH?D macro Din MOVE?BB Din, Shift MOVE?BB Din + 1 , Shift + 1 MOVE?BB Din + 2, Shift + 2 MOVE?BB Din + 3, Shift + 3 MOVE?CB 0 , Shift + 4 MOVE?CB 0 , Shift + 5 RST?RP endm Put24?D macro Din MOVE?BB Din, R2 MOVE?BB Din + 1 , R2 + 1 MOVE?BB Din + 2, R0 MOVE?CB 0, R0 + 1 RST?RP endm EndAsm ' Remainder[3]=0 overasm: HoursL=$fff0 HoursH=$7fff latd=18 debug "ready",13,10 pause 1000 MainLoop: gosub AddHourTenth Gosub ShowHourMeter goto MainLoop ;============================================================ AddHourTenth: HoursL = HoursL + 1 IF HoursL = 0 then HoursH = HoursH + 1 return ShowHourMeter: Test[0]=$a0 ;divisor 100000 Test[1]=$86 Test[2]=1 ;@ PutDIV?D _Hours @ PutSH?D _Hours ; take a shortcut and load shift regs directly CALL Div4824U ;divide by 100000 debug ,13,10 ;@ PutMulResult?D Remainder @ Put24?D Remainder ; only do a 24 bit load since answer is never bigger than that Result = DIV32 10000 Remains = R2 debug DEC QUOTL, Dec1 Result, ".",DEC4 Remains ,13,10 pause 1000 return ;************************************************************************** ;Div4824U ;Inputs: ; Dividend - Dividend:6 (0 - least significant!) ; Divisor - Test:3 (0 - least significant!) ;Temporary: ; Counter - Count ; Shift - Shift:6 ;Output: ; Quotient - Dividend:6 (0 - least significant!) ; Remainder- Rem:3 (0 - least significant!) ; ;Adaptation of 24x24 division by Tony Nixon with corrections ;by Frank Finster 3/15/2005. ;Code adapted by Andy Lee ;01-Sep-2006 Original version ;************************************************************************** Div4824U: asm ;--------------------------------------------------- ; SUBROUTINE - 48 by 24 BIT DIVISION movlw 48 movwf Counter ;movff Dividend+0, Shift+0 ;movff Dividend+1, Shift+1 ;movff Dividend+2, Shift+2 ;movff Dividend+3, Shift+3 ;movff Dividend+4, Shift+4 ;movff Dividend+5, Shift+5 clrf Dividend+0 clrf Dividend+1 clrf Dividend+2 clrf Dividend+3 clrf Dividend+4 clrf Dividend+5 clrf Remainder+2 clrf Remainder+1 clrf Remainder+0 dloop bcf STATUS, C rlcf Shift+0 rlcf Shift+1 rlcf Shift+2 rlcf Shift+3 rlcf Shift+4 rlcf Shift+5 rlcf Remainder+0 rlcf Remainder+1 rlcf Remainder+2 movf Test+2, w subwf Remainder+2, w btfss STATUS, Z bra nochk movf Test+1,w subwf Remainder+1,w btfss STATUS, Z bra nochk movf Test+0,w subwf Remainder+0,w nochk btfss STATUS, C bra nogo movf Test+0,w subwf Remainder+0 btfsc STATUS, C bra nodec_remainM decf Remainder+1, f movf Remainder+1, w xorlw 0xff btfsc STATUS, Z decf Remainder+2, f nodec_remainM movf Test+1, w subwf Remainder+1, f btfss STATUS, C decf Remainder+2, f movf Test+2, w subwf Remainder+2, f bsf STATUS, C nogo rlcf Dividend+0 rlcf Dividend+1 rlcf Dividend+2 rlcf Dividend+3 rlcf Dividend+4 rlcf Dividend+5 decfsz Counter, f goto dloop return endasm
Last edited by richard; - 3rd December 2024 at 00:06.
Warning I'm not a teacher
Thanks Richard,
I won't pretend to comprehend the assembly voodoo but I think we can shave another BYTE worth of RAM off that thing by declaring Result as a BYTE instead of a WORD. At least it seems to work :-)
/Henrik.
Richard,
Just wanted to thank you once again, the code is now incorporated in my project and I can display my two 32bit variables nicely.
I hardcoded the divisor to 100k and got rid of the Divisor variable. It grew the codebase by 230bytes and 34bytes of RAM out of which 11 is an array to which I write the resultCode:DWORDtoString: CALL DivBy100k ' QUOTL top word, Remainder low word. ' Get Remainder into PBP system variables in preparation for DIV32 ASM MOVE?BB Remainder, R2 MOVE?BB Remainder + 1 , R2 + 1 MOVE?BB Remainder + 2, R0 MOVE?CB 0, R0 + 1 RST?RP ENDASM Result = DIV32 10000 Remains = R2 IF QUOTL THEN ARRAYWRITE DWordString, [DEC QUOTL, DEC Result, DEC4 Remains, 0] ELSEIF Result THEN ARRAYWRITE DWordString, [DEC Result, DEC4 Remains, 0] ELSE ARRAYWRITE DWordString, [DEC Remains, 0] ENDIF
Is it possible to describe the method or algorithm to get the decimal from the possible 8 hexadecimal of 32 bit number.... the conversion itself is pretty straight forward but the 8 bit manipulations are confusing...
.
.![]()
Bookmarks