News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Question about division code

Started by Cobra, December 19, 2006, 08:20:05 PM

Previous topic - Next topic

Cobra

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]

u

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

Please use a smaller graphic in your signature.

raymond

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
When you assume something, you risk being wrong half the time
http://www.ray.masmcode.com

u

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
Please use a smaller graphic in your signature.

Cobra

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