    page    96,132
;§∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞§
;§                                                                          §
;§              ディレクトリエントリ  ソート  ユーティリティ                §
;§                                                                          §
;§                                     ＤＳＯＲＴ．ＥＸＥ  Ｖｅｒ１.１１    §
;§                                                                          §
;§                   Copyright (C) by 福地 邦雄 1991. All rights reserved.  §
;§∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞§
    .MODEL  SMALL,C
;
REVERSE     equ 1
FALSE       equ 0
direntrysize    equ 20h
;
    public  dirqsort,dirswap,sortfuncall
;
    .code
;
;------------------------------------------------------------------------------
;
;   dirqsort
;       ディレクトリエントリのクイックソート
;
;   TYPE    near call
;   IN      DS = ソートバッファセグメント
;           [SP+2] = ソートバッファオフセット
;           [SP+4] = 要素数
;           ES:[SP+6] = 比較関数リストアドレス
;   OUT     なし
;   保存レジスタ    bp,ds
;
;------------------------------------------------------------------------------
;
dirqsort    proc    sortobj,elmcount,funclist
    local cmpobj,chgedobj,cmpcount,chgcount
;
;   @if (elmcount,gt,1),L           ; 要素数２以上ならソート実行
      cmp   elmcount,1
      jg    @i0001
      jmp   @i0002
@i0001:
        mov     si,sortobj
        mov     di,direntrysize
        add     di,si
        cmp     elmcount,02
        mov     cmpobj,di
;       @if (zf,on)                 ; 要素数２なら直接比較
          jnz   @i0003
            mov     bx,funclist
            call    sortfuncall
            test    ax,ax
;           @if (zf,off),and,(sf,off)   ; エントリ１が大きい時は入れ換え
              jz    @i0004
              js    @i0004
                mov     di,cmpobj
                mov     si,sortobj
                call    dirswap
;           @ifend
@i0004:
;       @else                       ; 要素数３以上
          jmp   @i0005
@i0003:
            mov ax,elmcount         ; 比較の基準を配列の真ん中から取り出す
            mov     bx,2
            cwd
            idiv        bx
            mov     bx,direntrysize
            imul    bx
            mov     si,sortobj
            mov     di,si
            add     di,ax
            call    dirswap
            mov     ax,sortobj      ; 準備
            mov     chgcount,0
            mov     cmpcount,1
            mov     chgedobj,ax
;           @do repeat
@d0001:
                mov     ax,cmpcount ; 比較終了か？
;               @if (ax,ge,elmcount)
                  cmp   ax,elmcount
                  jl    @i0006
;                   @doexit
                      jmp   @d0002
;               @ifend
@i0006:
                mov     di,sortobj  ; 比較関数呼び出し
                mov     si,cmpobj
                mov     bx,funclist
                call    sortfuncall
                test    ax,ax
;               @if (sf,on)         ; 比較対象エントリが小さい時
                  jns   @i0007
                    inc     chgcount
                    add     chgedobj,direntrysize
                    mov     si,cmpobj
                    mov     di,chgedobj
;                   @if (si,/=,di)
                      cmp   si,di
                      je    @i0008
                        call      dirswap
;                   @ifend
@i0008:
;               @ifend
@i0007:
                add     cmpobj,direntrysize ; 次の比較対象へ
                inc     cmpcount
;           @doend
              jmp   @d0001
@d0002:
            mov     si,sortobj      ;
            mov     di,chgedobj
;           @if (si,/=,di)
              cmp   si,di
              je    @i0009
                call      dirswap
;           @ifend
@i0009:
            push    funclist        ; 再帰呼び出し 1
            push    chgcount
            push    sortobj
            call    dirqsort
            mov     bx,chgedobj     ; 再帰呼び出し 2
            add     bx,direntrysize
            mov     cx,elmcount
            sub     cx,chgcount
            dec     cx
            push    funclist
            push    cx
            push    bx
            call    dirqsort
;       @ifend
@i0005:
;   @ifend
@i0002:
    ret     6
;
dirqsort    endp
;
;------------------------------------------------------------------------------
;
;   dirswap
;       ディレクトリエントリの交換
;
;   TYPE    near call
;   IN      DS:SI = エントリ１アドレス
;              DI = エントリ２アドレス
;   OUT     なし
;   保存レジスタ    bx,dx,si,di,bp,ds,es
;
;------------------------------------------------------------------------------
;
dirswap proc
;
    cld
    mov     cx,direntrysize/2
swaploop:
    mov     ax,[si]
    xchg    [di],ax
    mov     [si],ax
    lea     si,[si+2]
    lea     di,[di+2]
    loop    swaploop
;
    ret
;
dirswap endp
;
;------------------------------------------------------------------------------
;
;   sortfuncall
;       ソート用比較関数列の呼び出し
;
;   TYPE    near call
;   IN      ES:BX = 比較関数列のアドレス
;           DS:SI = エントリ１アドレス
;              DI = エントリ２アドレス
;   OUT     AX = 比較結果
;   保存レジスタ    si,di,bp,ds,es
;
;------------------------------------------------------------------------------
;
sortfuncall proc
;
;   @do until
@d0003:
        call    word ptr es:[bx]    ; 比較関数呼び出し
;       @if (word ptr es:[bx+2],=,REVERSE)  ; 逆順指定の時は結果を反転
          cmp   word ptr es:[bx+2],REVERSE
          jne   @i0010
            neg     ax
;       @ifend
@i0010:
;       @if (ax,/=,0)               ; 比較して違いがあれば終了
          or    ax,ax
          je    @i0011
            jmp     compareend
;       @ifend
@i0011:
        lea     bx,[bx+4]           ; 次の比較関数へ
;   @doend (word ptr es:[bx],=,0)   ; 関数列の終了まで
      cmp   word ptr es:[bx],0
      jne   @d0003
compareend:
    ret
;
sortfuncall endp
;
    end
