Lately, I needed dividing two 8-bit registers by various 8-bit constants. I ended up having one common code for all constant divisors [1 to 255] [2 to 255].
I liked sharing it here since I couldn’t find a similar/equivalent one by searching on the internet. But it is possible that I missed it and someone else did it already.
Its speed is not bad [39/34 cycles, max/min ; excluding RET and RCALL].
It uses 33 words.
To use this code (posted below), only the constant divisor ‘reg_N’ needs to be changed.
By the way, I checked the rounding of this division code for every constant divisor [1 to 255] [2 to 255] and for all dividend values [0 to 65535].
Kerim
Added: An updated version on post #5 , it suits better the registers of 'my' assembly programs (not recommended).
Edited: Another version on post #37 , so far, it is the optimum version of the code, in term of speed (35 cycles) and memory space (29 words).
By avrcandies
Edited: Another version on post #45 , another good version of the code.
By grohote
;============================================================== ; *R* Division of 16-bit register {A} by 8-bit constant {N} *** ;============================================================== ; {R}={A}/{N} = r17:r16 / {N} = r17:r16 * {Kd} /256 /256 then rounding ; {A} dividend in r17:r16 [0 to 65535] ; {N} constant divisor [1 to 255] ; {R} result in r21:r20 , {A}/{N} rounded ; {Kd} = round(256*256/{N},0), the division constant ; {Kr} = INT[ (1-{N})/2 ] , the rounding constant ; used registers: r19,r18,r14,r13,r1,r0 ; 33 words , excluding RET and RCALL ; 41, 44, 45, or 46 cycles = 34c|37c|38c|39c code + 4c RET + 3c RCALL .set reg_N = 113 ; {N} .set reg_Kd=(2*256*256/reg_N+1)/2 ; {Kd} .set reg_Kr=(1-reg_N)/2 ; {Kr} D16_nnn: LDI r18, low(reg_Kd) ;1abcd MOV r13, r18 ;1abcd LDI r18, high(reg_Kd) ;1abcd MOV r14, r18 ;1abcd, 4abcd ; r14:r13 = reg_Kd ; multiplicand in r17:r16 = {A} ; multiplier in r14:r13 = {Kd} ; mul. result in r21:r20:r19:r18 ; valid result in r21:r20 MUL r17, r14 ;2abcd MOVW r21:r20, r1:r0 ;1abcd MUL r16, r13 ;2abcd MOVW r19:r18, r1:r0 ;1abcd MUL r17, r13 ;2abcd CLR r13 ;1abcd ADD r19, r0 ;1abcd ADC r20, r1 ;1abcd ADC r21, r13 ;1abcd MUL r14, r16 ;2abcd ADD r19, r0 ;1abcd ADC r20, r1 ;1abcd ADC r21, r13 ;1abcd +17abcd= 21abcd ; {B} = r21:r20 = r17:r16 * r14:r13 /256/256 = {A}*{Kd}/256/256 ; {R} = {B} or {B}+1 ; for rounding LDI r18, reg_N ;1abcd MOV r13, r18 ;1abcd ; r13 = {N} MUL r20, r13 ;2abcd MOV r18, r0 ;1abcd MOV r19, r1 ;1abcd MUL r21, r13 ;2abcd ADD r19, r0 ;1abcd, +9abcd= 30abcd ; {C} = r19:r18 = {B}*{N} = r21:r20 * r13 ; the following conditions were deduced empirically ; if( Carry_1=0, {R}={B}, if( Zero_2=1 OR Carry_2=0, {R}={B}, {R}={B}+1 ) ) SUB r18, r16 ;1abcd SBC r19, r17 ;1abcd ; {D1} = r19:r18 = {C} - {A} = r19:r18 - r17:r16 BRCC DIV_ret ;2a|1bcd +4a=[34a] ; if Carry_1=0, {R}={B} SUBI r18, low(reg_Kr) ;1bcd SBCI r19, high(reg_Kr) ;1bcd ; {D2} = r19:r18 = {D1} - {Kr} = r19:r18 - {Kr} BREQ DIV_ret ;2b|1cd, +7b=[37b] ; if Zero_2=1, {R}={B} BRCC DIV_ret ;2c|1d, +8c=[38c] ; if Carry_2=0, {R}={B} SUBI r20, low(-1) ;1d SBCI r21, high(-1) ;1d, +9d=[39d] ; {R}={B}+1 DIV_ret: RET ;4 ; {R} = r21:r20 = {B} or {B}+1 [ {A}/{N} rounded ]