I have a routine that divides a number by 655. I would think that listing #1 would be the logical choice. Listing #2 is what a C compiler generated. They both get the same results. Which one is better / faster and why?
listing #1
mov eax, 65535
mov ecx, 655
div ecx
listing #2
mov eax, 65535
mov ecx, eax
mov eax, -1875359765
mul ecx
sub ecx, edx
shr ecx, 1
add ecx, edx
shr ecx, 9
mov eax, ecx
[/font]
Listing 3 > Listing 2 > Listing 1
Because div is slow.
listing #3 :
mov eax,65535
mov edx, 3357287413 ; generated by the app "MagicDivider" from TheSvin and Ewayne
inc eax
mul edx
SHR edx, 9
mov eax,edx
Cobra
Before you divide the content of EAX by anything, you must
- either zero the EDX register before you perform the division if the content of EAX will always be positive,
- or use the cdq instruction to extend the sign of the EAX register to EDX and then use the idiv instruction for signed division.
As for the "magic multipliers", they may be fine if you use a constant divider known at programming time, or you would use the same variable several times as a divider. Otherwise, going the "magic multiplier" route will simply waste time.
Using the "magic multipliers" to replace signed divisions can also be tricky. (The suggested codes would definitely not work.)
Raymond
Ookay... signed division using magic:
mov eax,-65535 ; put argument value
mov ecx,eax
sar ecx,31 ; ecx shows what the sign is: 0 for positive, -1 for negative
xor eax,ecx ; make eax absolute, pass 1
sub eax,ecx ; make eax absolute, pass 2
mov edx,3357287413 ; magic, pass 1
inc eax ; magic, pass 2
mul edx ; magic, pass 3
shr edx,9 ; magic, pass 4
add edx,ecx ; restore sign, pass 1
xor edx,ecx ; restore sign, pass 2
mov eax,edx ; get result into eax
Weird acrobatics here just to avoid jumps :toothy
Quote from: raymond on December 20, 2006, 03:23:55 AM
Before you divide the content of EAX by anything, you must
- either zero the EDX register before you perform the division if the content of EAX will always be positive,
- or use the cdq instruction to extend the sign of the EAX register to EDX and then use the idiv instruction for signed division.
I forgot to type the xor edx,edx in there. The "magic numbers" come from the C compiler generated output. The routine I have returns a value in the range of 0..65535. It just opens up the mixer and retrieves the the current sound value, returns it and divides by 655 to return a value in the range of 0..100 for the volume. If I'm unsure about something I create a 'test' routine in C and examine the generated code. It's a bit easier (for me anyway) to get a handle on things that way at times.
Other than the usual places listed on here, are there any other good optimization tutorials around any where?
- Chuck :U