Saturday, November 3, 2018

How does this assembly code divide by 1000 without calling idiv

I am trying to understand the trick assembly uses to divide numbers using multiplication and bit shifts. In this example I am working with a battery.



typedef struct{
short volts;
char percent;

char mode;
} batt_t;


Notice that this struct takes up 32 bits which means it can be stored compactly in %edi. I want to do volts/1000. The assembly code for this process is



    movswl  %di, %eax            #moves volts to %eax
imull $-31981, %eax, %edx #multiplies volts by (2^25)/1000
shrl $16, %edx #volts times (2^9)/1000
addl %edi, %edx #Adding the original number???

sarw $9, %dx #Dividing by 2^9
movl %edi, %r8d #And from here it subtracts a 1
sarw $15, %r8w #if the original short was negative???
subl %r8d, %edx
movswl %dx, %ecx #stores result in %ecx


I don't understand the difference between shr and sar in this case. What I am especially confused about is why it decides to add the original number back on and why it subtracts a one at the end if it's dividing a negative number.



Note




The left 16 bits of %edi contains the two chars we don't need for this operation, but that's okay because the code is clever enough to prevent these bits from affecting the final answer.

No comments:

Post a Comment

plot explanation - Why did Peaches' mom hang on the tree? - Movies & TV

In the middle of the movie Ice Age: Continental Drift Peaches' mom asked Peaches to go to sleep. Then, she hung on the tree. This parti...