Well done! Some ideas to improve it: 1) Saving carry in counter can be made like at http://www.piclist.com/techref/default.asp?from=/techref/piclist/../microchip/math/&url=div/24by16.htm to save carry in counter: rlf BitCount, f to check carry and BitCount.0 after subtraction: SKPNC ;if no borrow BSF BitCount, 0 ;set bit 0 of counter (saved carry) BTFSC BitCount, 0 ;if no borrow GOTO DIVIDE_SKIP_48by24 ;jump to restore carry and counter: CLRC ;copy bit 0 to carry RRF BitCount, F ;and restore counter Total: 7 instructions instead of 10 (same savings as in Scott's proposal though) It's hard to beat Scott :) 2) Clearing carry not necessary before loop. 3) Using slightly different method can improve speed a lot with small code increase. That can be achieved if you don't restore the remainder in the same iteration. You can do just one subtraction/addition in each iteration. Subtract from remainder if remainder is positive or zero and add to remainder if remainder is negative. For example let's divide 10101100 (172) by 1001 (9) using this nonrestoring method: C Temp Dividend = ==== ======== 0 0001 0101100x (x - garbage after initial shift) - 1001 ---------------- 0 1000 0101100x -> borrow, first bit of result is 0 next iteration (2nd), 1 0000 101100x0 + 1001 ----------------- 0 1001 101100x0 -> no carry, next bit of result is 0 next iteration (3rd), 1 0011 01100x00 + 1001 ------------------ 0 1100 01100x00 -> no carry, next bit of result is 0 next iteration (4th), 1 1000 1100x000 + 1001 ------------------ 1 0001 1100x000 -> carry, next bit of result is 1 next iteration (5th), 0 0011 100x0001 - 1001 ------------------ 0 1010 100x0001 -> borrow, next bit of result is 0 next iteration (6th), 1 0101 00x00010 + 1001 ------------------ 0 1110 00x00010 -> no carry, next bit of result is 0 next iteration (7th), 1 1100 0x000100 + 1001 ------------------ 1 0101 0x000100 -> carry, next bit of result is 1 last iteration (8th), 0 1010 x0001001 - 1001 ----------------- 1 0001 x0001001 -> no borrow, next bit of result is 1 So, result is 00010011 (19), remainder is 1, which looks correct. Probably, using this method you don't have to save carry in counter, which is rather good. Hey, the code size may be even smaller! And twice as fast! So the algorithm in loop is: 1) Shift left divider to temp, and temp to carry 2) If carry is set, add divider to remainder (temp). If carry is clear, subtract divider from remainder (temp) 3) Repeat from 1 (carry contains next result bit) Enjoy :) Nikolai P.S. Probably the routine below uses big endian notation, because the end (Ram, or Ram+0) is MSB! But it doesn't matter actually, because the routine will be the same for little endian, except for different registers numbering. -------------------------------------------------------------------------------- Subject: [PIC]: Number crunching, enclosed is 48/24, have fun :) From: Kubek Tony (tony.kubek@FLINTAB.COM) Date: Wed Oct 25 2000 - 06:36:43 PDT -------------------------------------------------------------------------------- Hi, continuing my effort to build up a small math library, time has come today for the 48bit divided by 24 bit. Thanks to Nicolai's pseudo-code it only took about an hour or so ( thanks ! ), it contains a very clever use of the bitcounter for saving the carry. Without further ado: ;*********************************************************************** ; DIVIDE_48by24 - Routine to divide a 48 bit number with a 24 bit number ; result upto 48 bits ! ; ; Formula: Dividend = Dividend/Divisor ; ; Format: Little endian, Ram = msb, Ram+x = lsb ( where x=bytesize-1) ; Ram used: Dividend 6 bytes ( 48 bits ) ; Divisor 3 bytes ( 24 bits ) ; Temp 3 bytes ; BitCount 1 byte for loop counting ( and temp. saving of carry ) ; ; Divisor is preserved ; Dividend holds result ; Returns with zero in W if failed ( division with zero ) ; Else returns with one in w ; ; Based on pseudo-code from Nikolai Golovchenko [golovchenko@mail.ru] ; ; DIVIDE_48by24 ; Test for zero division MOVF Divisor,W IORWF Divisor+1,W IORWF Divisor+2,W BTFSC STATUS,Z RETLW 0x00 ; divisor = zero, not possible to calculate return with zero in w ; prepare used variables CLRF Temp CLRF Temp+1 CLRF Temp+2 MOVLW D'48' ; initialize bit counter MOVWF BitCount CLRC ; clear carry at entry DIVIDE_LOOP_48by24 ; a) first time carry cleared ; b) every other bit carry contains the result of ; last subtraction ( division ). ; shift in carry as lowest bit RLF Dividend+5,F RLF Dividend+4,F RLF Dividend+3,F RLF Dividend+2,F RLF Dividend+1,F RLF Dividend,F ; shift in highest bit from dividend through carry in temp RLF Temp+2,F RLF Temp+1,F RLF Temp,F ; save carry status in bitcounter temporarily ( possible overflow from temp msb ) BTFSC STATUS,C BSF BitCount,7 ; set bit ( carry was set, temp>24bit ) ; subtract 24 bit divisor from 24 bit temp MOVF Divisor+2,W ; get lsb SUBWF Temp+2,F ; subtract MOVF Divisor+1,W ; get middle byte SKPC ; if overflow ( from prev. subtraction ) INCFSZ Divisor+1,W ; incresase source SUBWF Temp+1,F ; and subtract from dest. MOVF Divisor,W ; get top byte SKPC ; if overflow ( from prev. subtraction ) INCFSZ Divisor,W ; increase source SUBWF Temp,F ; and subtract from dest. BTFSC STATUS,C ; save carry status again to use for negative check BSF BitCount,7 ; yes carry was set. ; if was carry set ( saved in top bit of bitcount ): ; a) Temp overflowed ( i.e. temp > divisor ) ; b) Result was positive from subtraction ( i.e. temp > divisor ) ; if carry was cleared: ; a) temp < divisor BTFSC BitCount,7 GOTO DIVIDE_SKIP_48by24 ; carry was set, subtraction ok, continue with next bit ; result of subtraction was negative restore temp MOVF Divisor+2,W ; get LSB of divisor ADDWF Temp+2,F ; add it to the lsb of temp MOVF Divisor+1,W ; middle byte BTFSC STATUS,C ; check carry for overflow from previous addition INCFSZ Divisor+1,W ; if carry set we add 1 to the source ADDWF Temp+1,F ; and add it if not zero in that case Product+Multipland=Product MOVF Divisor,W ; MSB byte BTFSC STATUS,C ; check carry for overflow from previous addition INCFSZ Divisor,W ADDWF Temp,F ; handle overflow DIVIDE_SKIP_48by24 CLRC ; clear carry ; carry should now reflect if divison was possible ( i.e. temp > divisor ) ; so if it was set, set carry to be shifted in as lowest bit of Dividend BTFSC BitCount,7 BSF STATUS,C ; restore carry BCF BitCount,7 ; clear bit used for saving carry DECFSZ BitCount,F ; decrement loop counter GOTO DIVIDE_LOOP_48by24 ; another run ; finally shift in the last carry RLF Dividend+5,F RLF Dividend+4,F RLF Dividend+3,F RLF Dividend+2,F RLF Dividend+1,F RLF Dividend,F NOP NOP RETLW 0x01 ; done Tried with a handful of numbers and everything seems ok, but please don't take my word on it :) Use at will/risk/leisure/etc. And oh..pic-code second time this week on the list ( not counting Scott's challenge, nice one ) where will it end ? /Tony Tony Kubek, Flintab AB ???????????????????????????????????????????????????????????? E-mail: tony.kubek@flintab.com ???????????????????????????????????????????????????????????? -- http://www.piclist.com hint: The list server can filter out subtopics (like ads or off topics) for you. See http://www.piclist.com/#topics -- http://www.piclist.com hint: The list server can filter out subtopics (like ads or off topics) for you. See http://www.piclist.com/#topics