[A83] help for a routine - ASM Multiplying and dividing shortcut


[Prev][Next][Index][Thread]

[A83] help for a routine - ASM Multiplying and dividing shortcut




recently someone asked:
"I need a routine that can make this :
Input :
- h, e
Output:
- a=(h*256)/e"
There in fact a very fast and quick way to do 
multiplication on all microcontrollers.

Let's say us humands wanted to multiply a number (say 2) by 
10 in decimal. To do that we shift the 2 left one place and 
add a zero to the end so the result is 20. If we wanted to 
to multiply 2 by 10^2 we shift it left two etc. 

Microcontrollers however count from 1 - 2 not one to ten. 
This changes our scaling but not the concept. Say we wanted 
to multiply 02h (02 hexadecimal = 0000 0010 binary) by 02h. 
Because 02h is to binary what 10 is to decimals we can do 
the same thing as we did above. Simply take our number 02h 
and shift it to the left one and add a zero to the end, So 
0000 0010 becomes 0000 0100 which equals 04h (and what do 
you know 2 x 2 = 4). So if we wanted to multiply 2 by 8, 8 
= 2^3. So we need to shift 2 to the left 3 places and add 3 
zero's ie. 0000 0010 becomes 0001 0000 or 16h.

Neat huh! But if I want to multiply by like 17 or 15? Well 
this is where arithmetic comes in. 17 and 15 are one off 
16. 16 = 2^4 therefor 17 = 2^4 + 1 and 15 = 2^4 - 1. So to 
multiply a number by 17 we shift the number where 
multiplying to left by 4 and add the number. So 0000 0010 
becomes 0010 0000 (2 shifted to the right 4 = x 16) + 0000 
0010 (add our original numer to = x 17) = 0010 0010. Which 
is 34! Yay!!!!!

I know what your thinking how do I do this in ASM? Well 
actually I don't know specifically (I know more about 
68HC11's then z80's). I believe the command is something 
like SHL but you'll have to look up z80 opcodes
so the code to multiply 2 by 17 looks something like this

LDA a,2 ;load accumulator a with 2
LDA b,a ;put value of a in b
SHL a   ;shift accumulator a left one (if it is indeed SHL)
SHL a
SHL a
SHL a   ;shift to the left x 4 = multiply by 16
ADD a,b ;add our original value = multiply by 17

And in theory if the syntax is correct a should now equal 34
(I'm sorry in advance if the coding above is wrong but the 
concept is right).

So what's the advantage of all this?? The answer is speed
if you just use the multiply command the processor has to 
add up 2, 17 times in a big loop. This would take about 4 
clock cycles x 17 = 68 clock cycles. Yukky! Where as the 
code above takes about 20. (these are rough estimates only).

So what about dividing huh? Well dividing is just like 
upside down multiplying :)
So to divide by 2 we shift right one. To divide by 4 we 
shift right two. etc. 
There is however no shortcut way to divide by 17. So the 
best way to do that is to change your accuracy. Make it so 
your dividing by 16. This may still work fine because 
microcontrollers truncate. If i had 32 / 10 the 
microcontroller returns 3. in fact even if i had 38/ 10 the 
answer is still 3. So 34 / 17 returns 2 which whould be the 
same as if you had of just shifted in right 4 places.

Footnote: A word of warning this stuffs up majorly for the 
hl * 256 thing above. Because hl is 16 bits made up of two 
registers if hl is 255 or greater the result will always be 
greater then 16 bits. Because micro-controllers truncate to 
the most significant it you used the multiply command it 
would just return your original value, however logically 
shifting left by 8 (256 = 2^8) would more then likely make 
you lose your most significant bits and return a wrong 
arguement. 







Follow-Ups: