QuickSortLib:

;****************************************************
; Quick sort of the array in the memory.
;
;  ptrArray       - pointer to the memory array.
;  ElementSize    - size of one array element in bytes.
;  iBegin         - index of the first element
;  iEnd           - index of the last element
;  ptrCompareProc - pointer to procedure that compares two elements.
;
; ptrCompareProc have interface:
;  proc CompareSomething, ptrElement1, ptrElement2
;    returns: c=1 if elements are not properly sorted.
;             c=0 if elements are sorted, i.e.
;                 element1 should be before element2
;****************************************************


proc QSort, ptrArray, ElementSize, iBegin, iEnd, ptrCompareProc
begin
        push    esi edi ebx
        mov     esi, [ptrArray]
        mov     edi, [ptrCompareProc]
        mov     ebx, [ElementSize]

        stdcall DoQSort, [iBegin], [iEnd]
        pop     ebx edi esi
        return
endp

;*****************************************************
; Procedure for internal call from QSort procedure.
;*****************************************************
proc DoQSort, Left, Right
begin
        push    ecx

        mov     ecx, [Left]     ; i variable
        mov     eax, ecx
        mov     edx, [Right]    ; j variable
        add     eax, edx
        sar     eax, 1
        imul    eax, ebx
        imul    ecx, ebx
        imul    edx, ebx
        add     eax, esi
        add     ecx, esi
        add     edx, esi

.repeat:
        sub     ecx, ebx
        add     edx, ebx

.whylei:
        add     ecx, ebx
        stdcall edi, ecx, eax
        jnc     .whylei

.whylej:
        sub     edx, ebx
        stdcall edi, eax, edx
        jnc     .whylej

        cmp     edx, ecx
        jl      .next

        call    SwapElements

        push    edx
        cmp     eax, ecx
        je      @f
        mov     [esp], ecx
        cmp     eax, edx
        je      @f

        mov     [esp], eax
@@:
        pop     eax

        add     ecx, ebx
        sub     edx, ebx

.next:
        cmp     ecx, edx
        jle     .repeat

        mov     eax, edx
        sub     eax, esi
        cdq
        idiv    ebx

        cmp     [Left], eax
        jge     .leftok

        stdcall DoQSort, [Left], eax

.leftok:
        mov     eax, ecx
        sub     eax, esi
        cdq
        idiv    ebx

        cmp     eax, [Right]
        jge     .rightok

        stdcall DoQSort, eax, [Right]

.rightok:
        pop     ecx
        return
endp



;********************************************
; Swaps two elements of the array with
; pointers in:
;   Element1 - ecx
;   Element2 - edx
;   ElementSize - ebx
;********************************************
proc SwapElements
begin
        push    esi eax

        xor     esi, esi
.loop:
        mov     al, [ecx+esi]
        xchg    al, [edx+esi]
        mov     [ecx+esi], al

        inc     esi
        cmp     esi, ebx
        jne     .loop

        pop     eax esi
        return
endp




proc CompareIntAscending, ptrElement1, ptrElement2
begin
        push    eax esi edi

        mov     esi, [ptrElement1]
        mov     edi, [ptrElement2]

        mov     eax, [esi]
        cmp     eax, [edi]
        jl      .qfalse

        stc
        pop     edi esi eax
        return


.qfalse:
        clc
        pop     edi esi eax
        return
endp



DispSize 'QSort lib', $ - QuickSortLib