Friday, 30 September 2016

assembly - How does division by constant work in avr-gcc?





In avr assembly, I wanted to divide a number by a constant.
I checked how to see how avr-gcc does it.
So in a c file I have :



#include 


uint8_t divide_by_6(uint8_t x) {
return x / 6;
}


and when I run avr-gcc -O3 -mmcu=atmega16 -D__AVR_ATmega16__ -S main.c it gives me:



divide_by_6:
ldi r25,lo8(-85)
mul r24,r25

mov r24,r1
clr r1
lsr r24
lsr r24
ret


But I do not understand what this assembly is doing.
How does this assembly code perform division?


Answer




-85 is 0xFFFFFFFFFFFFFFAB, so lo8(-85) is 0xAB, which is 171.



The code is multiplying the argument by 171, and then returning the most significant byte of the product, shifted right by 2 (i.e. divided by 4).



So it's effectively returning x * 171 / (256 * 4) == x * 171 / 1024, which is approximately == x * 1 / 6 == x / 6.


No comments:

Post a Comment

c++ - Does curly brackets matter for empty constructor?

Those brackets declare an empty, inline constructor. In that case, with them, the constructor does exist, it merely does nothing more than t...