Help with assembly language divide.
mynet43
Posts: 644
I need to divide a 32 bit unsigned number by a constant. The constant is either 72 or 10 (1001000 or 1010).
Would someone please help me with an optimized way to divide a 32 bit number by these two constants.
Thank you for your help.
Jim
Would someone please help me with an optimized way to divide a 32 bit number by these two constants.
Thank you for your help.
Jim
Comments
Usage
Thank you for the sample code. I'll take a look at it. I think this should help. It looks like your pre loop may be the trick.
Regards,
Jim
is a repeating binary expansion that can be computed by various tricks is a few shifts and adds.
Mark. I need about 4 digits decimal accuracy from a dividend ranging from 1_600_000 to 1_600_000_000. Can you give me an example of your coding suggestion for divide by 10. If it works, I'm happy to have a dedicated routine just for this.
Kye. In your code, it looks like the initial values of LNDivideBuffer and LNDivideCounter depend ONLY on the value of LNDivideDivsor. If this divisor is a constant, then I should be able to precalculate these values, use them as constants, and greatly reduce the initialization and the number of loops required to get the answer. Does this seem right?
Thanks for all your help!
Jim
Are the values in +1 steps or +512 steps?, as I try to see if the lower 9bits are always unused.
some info on how to use shr to help out.
http://www.tofla.iconbar.com/tofla/arm/arm02/index.htm
The value comes from cnt. It's the time it takes an engine distributor to make one revolution, based on the input from a hall-effect sensor.
I have twelve events I have to process during each revolution, so time is critical at 6000 RPM.
For this application, I'm not sure the last 9 bits matter. So what did you have in mind?
All these ideas are really great!
Thanks for your help.
Jim
Add #256 to value to round it, andn #511 to mask out the lower 9bits.
Divide by 10 or 72
Remember, your value now have a decimal point at 9th bit (you just divided it by 512)
so cmpsub with #5120 to see how many times you can subtract #10.0 from your main value.
But as I have not tested it, you have to look up correct ways to div
The lower 9bits will be reserved for your decimal point value.
Of course this decimal point is all simulated.
and it's up to you to make sure and data added/subtracted also have a simulated 9bits of decimals.
As noted, 1/10 is a repeating binary fraction:
%.000_1100_1100_1100_1100_1100_1100_1100_1
and can probably ignore the lsb 1.
So multiplication starts with * %.1100,
sar x, #1
mov t1, x
sar t1, #1
add x, t1 ' now have %.1100 in x
followed by 6 repetitions of shifting that 4 bits right and adding to the accumulator, then a final right shift by three. Or shorten code by using intermediate results 1100_1100 or 1100_1100_1100.
Ah, yes but there is a cleverer trick than iterating, original a trick in HAKMEM I think:
OK, you've got the value x .00011, so you shift right 4 and add back, gives x.000110011, then you shift right 8, addback, gives x.00011001100110011,
shift right 16, add back and you have all 32 bits...
Fortunately 1/72 is also a simple repeating form: x .000000111000111000111000111000111....
so you shift right 3 and subtract from original, gives x.111, then shift right 6, then take this value and apply a similar procedure with shifts of 6, 12 and 24
[ if you like you can think of the divide by 10 example as first multiplying by 3/32, then by 17/16, then by 257/256, then by 65537/65536,
and 3 / 32 * 17 / 16 * 257 / 256 * 65537 / 65536 = 0.09999999995 ]