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