HowTo DIV MUL in Assembler, Motorola, for 8-bit Microcontroller with an 16-bit result

Deutsche Version weiter unten!

Hi!

I´ve got a problem with the Assembly language for Motorola 8-bit microcontrollers:

how can I divide/multiply 2 8-bit variables with an 16-bit result? syntax:

e.g. div-command

div A

Reply to
Kai
Loading thread data ...

Essentially the same way you learned to divide and multiply multi-digit numbers back in primary school, although you can only memorize the "kleine 1x1". ;-)

Bad idea. Rather multiply by 17, then divide by 20.

Or multiply by 217 = 256*85/100, and keep only the upper byte of the

16-bit result.
--
Hans-Bernhard Broeker (broeker@physik.rwth-aachen.de)
Even if all the snow were burnt, ashes would remain.
Reply to
Hans-Bernhard Broeker

the idea is bad becouse you have integer and the 1% value cannot carry the accuracy from the 100% value. Depending from the absolute values, the result can be very inaccurate

das merkt man, du solltest deshalb vielleicht nicht gleich in so vielen Gruppen posten

Es wird ein 16 bit Wert durch einen 8 bit Wert geteilt und das Ergebnis gibt einen 8 bit Wert. Bei 85% von einem 16 bit Wert ist das Ergebnis aber meist eben auch ein 16 bit Wert.

An Stelle von 85% ginge es Beispielsweise sehr einfach 87,5% auszurechnen. Hierzu schiebst du den 100% Wert 3 mal nach rechts was 12,5% vom Gesamtwert ausmacht. Sodann machst du eine Subtraktion

100%-12,5%=87,5%. Du kannst das auf diese Weise natürlich selbst noch etwas genauer hintricksen undem du z.Bsp. nochmal 3,125% (nochmals 2x rechts schieben) zusätzlich abziehst. So wird das Ergebnis immer genauer. Der Code geht dann natürlich nur für den einen Fall von 85%, aber danach hast du ja gefragt. Ist auch die schnellste und kleinste Lösung.

Wenn du es allgemein haben willst, würde ich bei

formatting link
die freie Version des HC08 Compilers runterladen und von dort die Integer Bibliothek rausklauen. Die Codelänge der Bibliothek ist wesentlich kleiner als die von Metrowerks und es sind auch die Quellen davon in der Demo drin so daß du sie mit anderen Werkzeugen zum übersetzen kriegen müsstest wenn du sie nicht nur verstehen willst.

Reply to
Janvi

On 5 Feb 2004 03:24:21 -0800, Kai hath writ:

Then you really should be posting in

comp.lang.Motorola-8-bit-microcontrollers (oder etwas anders)

and not in

comp.lang.asm370

Reply to
Dave Null

Better is to multiply first and then divide. To get the 85% value, first multiply by 85 (or 17) and then divide by 100 (or 20).

If you are trying to determine what 85% of 130/100 is, then that's a different problem. You will have to resort to scaled, fixed-point operations to obtain anything meaningful.

Reply to
Everett M. Greene

Well, this newsgroup is for IBM S/370 assembler.

(snip)

Well, on most machines I know about that is not a good way.

Much better is to multiply by 85 and then divide by 100.

That is the advantage of having multiplies where the product is twice as long, and divide where the dividend is twice as long.

Say the number was 143. Divide by 100 and you get 1, multiply by 85 and you get 85.

But if you multiply 143 by 85 you get 12155, and divide by

100 you get 121. Which one do you want?

Note, though, that S/370 doesn't have an 8 bit multiply instruction. It does have a 32 bit multiply with a 64 bit product, and divide with a 64 bit dividend, 32 bit divisor generating a 32 bit quotient and 32 bit remainder.

-- glen

Reply to
glen herrmannsfeldt

| glen herrmannsfeldt wrote: |> Kai wrote: | Well, this newsgroup is for IBM S/370 assembler. |> I´ve got a problem with the Assembly language for Motorola 8-bit |> microcontrollers: |>

|> how can I divide/multiply 2 8-bit variables with an 16-bit result? |> syntax:

| (snip)

|> Goal: i´d like to calculate 85% of a measured value. |> Idea (good, bad???): divide value by 100 and multiply t by 85 | | Well, on most machines I know about that is not a good way. | | Much better is to multiply by 85 and then divide by 100. | | That is the advantage of having multiplies where the product is | twice as long, and divide where the dividend is twice as long. | | Say the number was 143. Divide by 100 and you get 1, multiply | by 85 and you get 85. | | But if you multiply 143 by 85 you get 12155, and divide by | 100 you get 121. Which one do you want? | | Note, though, that S/370 doesn't have an 8 bit multiply | instruction. It does have a 32 bit multiply with a 64 bit | product, and divide with a 64 bit dividend, 32 bit divisor | generating a 32 bit quotient and 32 bit remainder.

Note that the System/370 (and older models) have a 16-bit multiply (MH = multiply halfword). ___________________Gerard S.

Reply to
gerard46

(snip)

It seems more natural to me to use the multiply with the

64 bit product followed by the divide, as there is no DH.

One could MH, sign extend the result, and then divide, though. It might be faster on some machines.

One could also M with the appropriate constant, and use the high half of the product for the result. The rounding might be a little different, but the result should be close.

0.85*2**32=3650722201.6 143*3650722201 will put 121 into the high word of the product.

-- glen

Reply to
glen herrmannsfeldt

Considering that

217/256=0.84765625 (error -0.0033), 218/256=0.85312500 (+0.0031),

thus (218*x) >> 8 can be implemented with unsigned 8x8=16 bit multiply and using only the most significant byte of the result (equivalent of shifting the 16 bit products right by 8 places). No division instructions needed.

A slightly better result can be obtained by rounding, e.g. checking the most significant bit of the discarded product byte and if this bit is 1, add 1 to the retained product byte.

Paul

Reply to
Paul Keinanen

As others have noted, some of the newsgroups Kai posted to aren't appropriate for his platform. However...

Your original value has only 8 bits of precision; how precise do you need that 85% to be? If it's OK to calculate 87.5%, then you can do the following:

Load the original value into the accumulator Shift it right 3 bits Subtract this from original value; result is .875 of original value.

If that's not precise enough, you can get very close to .85 with only a few more steps:

Load the original value into the accumulator Shift it right 2 bits Subtract this from original value; result is .75 of original value. Save a copy of this intermediate value Shift intermediate value right 3 bits Add intermediate value to this shifted value; result is 112.5% of intermediate value, 84.375% of oiginal value. That's right to 8 bits of precision.

Shifts, adds, and subtracts are much faster than multiplys or divides on microprocessors, so an algorithm like this is usually preferred for such "multiply by a constant" calculations.

--
Randy Hudson
Reply to
Randy Hudson

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.