Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Help improving a simple assembly function

Tags:

x86

assembly

I just handed in this function in an assignment. It is done (hence no homework tag). But I would like to see how this can be improved.

Essentially, the function sums the squares of all the integers between 1 and the given number, using the following formula:

n(n+1)(2n+1)/6

Where n is the maximum number.

The function below is made to catch any overflow and return 0 should any occur.

UInt32 sumSquares(const UInt32 number)
{
    int result = 0;
    __asm
    {
        mov eax, number  //move number in eax
        mov edx, 2       //move 2 in edx
        mul edx          //multiply (2n)
        jo end           //jump to end if overflow
        add eax, 1       //addition (2n+1)
        jo end           //jump to end if overflow
        mov ecx, eax     //move (2n+1) in ecx

        mov ebx, number  //move number in ebx
        add ebx, 1       //addition (n+1)
        jo end           //jump to end if overflow

        mov eax, number //move number in eax for multiplication
        mul ebx         //multiply n(n+1)
        jo end          //jump to end if overflow
        mul ecx         //multiply n(n+1)(2n+1)
        jo end          //jump to end if overflow
        mov ebx, 6      //move 6 in ebx
        div ebx         //divide by 6, the result will be in eax

        mov result, eax //move eax in result

end:
    }

    return result;
}

Basically, I want to know what I can improve in there. In terms of best-practices mostly. One thing sounds obvious: smarter overflow check (with a single check for whatever maximum input would cause an overflow).

like image 576
MPelletier Avatar asked Apr 15 '10 23:04

MPelletier


1 Answers

    mov eax, number  //move number in eax
    mov ecx, eax     //dup in ecx
    mul ecx          //multiply (n*n)
    jo end           //jump to end if overflow
    add eax, ecx     //addition (n*n+n); can't overflow
    add ecx, ecx     //addition (2n); can't overflow
    add ecx, 1       //addition (2n+1); can't overflow
    mul ecx          //multiply (n*n+n)(2n+1)
    jo end           //jump to end if overflow
    mov ecx, 6       //move 6 in ebx
    div ecx          //divide by 6, the result will be in eax

    mov result, eax //move eax in result

Strength reduction: add instead of multiply.

By analysis, fewer overflow checks (you can do better as you described).

Keep values in registers instead of going back to the argument on the stack.

Chose registers carefully so values that can be reused are not overwritten.

like image 99
Doug Currie Avatar answered Oct 05 '22 23:10

Doug Currie