## 16bit/16bit division by using assembly

9 posts / 0 new
Author
Message

Hi all,

In my application I am required to do a 16 bit by 16 bit division by using assembly language, it is not a problem if by using C language but my whole code are written in assembly, and also it is not a problem if the dividend is bigger than divisor, however, in my application the dividend is definitely bigger than divisor, the result is expected to be 0.1--0.5.

Anyone have idea about this division in assembly? I also consider if by this way was too fussy, I have to mix some C function in my assembly codes, I know GCC assembler can do this job, right? Could anyone show me some sample codes?

Thanks a lot

One easy way is to get GCC, then make a simple program with the muls, divs, whatever, generate a .LST file (assembly source) and get the assembly routines (they are at the end of the file).
As for the less than unit results, you can use fixed point math. Just set some power of 2 to be 1 (the unit), like 256 ( 2^8 ). Then you can have and process real numbers, with a certain precision (given by how big is your unit). The subject is extensive, just Google for it.

Embedded Dreams
One day, knowledge will replace money.

You don't mention if the numbers are signed or unsigned so I expect hey are unsigned. You also want a non-integer result.
I would probably implement a 32-bit by 32-bit divide with the numbers loaded into the upper 2 bytes and leaving the lower bytes as zeros. Then you can treat the 32-bit values as shifted 16-bit ones with the lower 16 bits of the result as the fraction you require.
EG 0x00008000 = 0.5, 0x00004000 = 0.25 etc.

I have coded for about 2 dozen architectures, and they all have their place.
Don't get too religious about them (but AVR is excellent!)

First, look at Atmel app notes on "16 Bit Arithmetics", AVR202 IIRC and "Multiply and Divide Routines" AVR200.

Then exercise the search feature on the forum (and hope the right hits are indexed ;) ). There were extensive discussions several years back, including some 24-bit stuff that might work well for you.

There may also be projects posted for extended arithmetic.

Or just write in C. :)

https://www.avrfreaks.net/index.p...

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

Thanks everyone for the hints. Actually I tracked lots of threads in the past years, but still a bit lost since the information is too much.

I am thinking if I can do the following:
Multiply the dividend by 2, then it will be bigger than the divisor(only feasible in my application) -> then right shift the result 1 bit. For instance, I have 0110 1011/0111 1010, I firstly do unsigned 1101 0110/0111 1011, after I get a result, I divide the result by 2.

Now I can get the result and remainder, however this is not the final step, later I will use this value in other calculations, what should I do?

Paul Turner wrote:
You don't mention if the numbers are signed or unsigned so I expect hey are unsigned. You also want a non-integer result.
I would probably implement a 32-bit by 32-bit divide with the numbers loaded into the upper 2 bytes and leaving the lower bytes as zeros. Then you can treat the 32-bit values as shifted 16-bit ones with the lower 16 bits of the result as the fraction you require.
EG 0x00008000 = 0.5, 0x00004000 = 0.25 etc.

Sorry I forgot to mention, the calculation is unsigned.

longwaytogo wrote:
Thanks everyone for the hints. Actually I tracked lots of threads in the past years, but still a bit lost since the information is too much.

I am thinking if I can do the following:
Multiply the dividend by 2, then it will be bigger than the divisor(only feasible in my application) -> then right shift the result 1 bit. For instance, I have 0110 1011/0111 1010, I firstly do unsigned 1101 0110/0111 1011, after I get a result, I divide the result by 2.

Now I can get the result and remainder, however this is not the final step, later I will use this value in other calculations, what should I do?

This won't work, after division you'll get (in your example) 0x01, then after the /2 (>>1) that bit will be shifted off and you'l end up with 0x00.
If 0.5 is maximum possible result you can get then left shift your dividend by 16 (<<16) after casting it to 32 bits (this is from your original question with 16 bit vars) do the divide then cast back to 16bits. This will discard the integer portion. 0x8000 will be equivalent to 0.5, 0xFFFF will be almost-but-not-quite 1.0.

Edward

Quote:
This will discard the integer portion. 0x8000 will be equivalent to 0.5, 0xFFFF will be almost-but-not-quite 1.0.

Edward

Thanks Edward for the quick reply, if dont bother too much could you explain the quoted part more specifically? Thanks a lot.

And by the way I am not quite understand, make the dividend to 32 bits. Then I will do division as 32bit/16bit, right? Now the result is already 16bits, how could I cast it back to 16bits and discard the integer part?