[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: