    page    96,132
;§∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞§
;§                                                                          §
;§              ディレクトリエントリ  ソート  ユーティリティ                §
;§                                                                          §
;§                                     ＤＳＯＲＴ．ＥＸＥ  Ｖｅｒ１.１１    §
;§                                                                          §
;§                   Copyright (C) by 福地 邦雄 1991. All rights reserved.  §
;§∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞§
    .MODEL  SMALL,C
    .data
;
    public  errorno         ;プログラム終了時のステータスに指定する
errorno     dw      ?           ;エラーコード
;
printmsg    db  'print error',0dh,0ah   ;標準プリントのエラー表示のメッセージ
prtmsgsiz   equ     $-printmsg
;
allocmsg    db  'memory allocation error',0dh,0ah   ;メモリ獲得エラーの
alcmsgsiz   equ     $-allocmsg              ;メッセージ
;
    .code
;
;------------------------------------------------------------------------------
;
;   getargs
;       コマンドライン入力を分解してポインタのリストにする
;       空白,タブを区切り文字とする   プログラム名はサポートされない
;
;   TYPE    near call
;   IN  ds=psp
;       200h以上のスタックサイズ
;   OUT ss:bp にファーポインタリストの先頭アドレス
;       ax に文字列の個数       ゼロフラグに個数のテスト結果
;       ディレクションフラグ ダウン方向
;
;   保存レジスタ    ds のみ
;
;------------------------------------------------------------------------------
;
stackwrk    equ 01c0h
argcwrk     equ word ptr [bp]
returnaddr  equ word ptr [bp+2]
strings     equ word ptr [bp+4]
cmdlen      equ ds:[80h]
cmdtop      equ 81h
SPC     equ 20h
TAB     equ 09h
;
    public  getargs
getargs proc    near
;
    sub     sp,stackwrk     ;文字列とポインタリスト領域の確保
    mov     bp,sp
    mov     ax,[bp+stackwrk]    ;リターンアドレスのセーブ
    mov     returnaddr,ax
    xor     ax,ax           ;ワーク領域&レジスタの初期化
    mov     argcwrk,ax
    mov     cx,ax
    lea     di,strings
    mov     cl,cmdlen       ;コマンドライン文字列長の取得
    mov     si,cx
    inc     cx
    mov     bx,cmdtop
    mov     byte ptr [si+bx],SPC    ;コマンドライン終端の改行コードを空白に
;
spaceloop:              ;空白,タブをスキップする
    cmp     byte ptr [bx],SPC
    je      nextchar
    cmp     byte ptr [bx],TAB
    jne     spaceout
nextchar:
    inc     bx
    loop    spaceloop
    jmp     argend
;
spaceout:               ;
    mov     ss:[di],bx      ;文字列の先頭オフセットのセーブ
    mov     word ptr ss:[di+2],0    ;文字列長さ初期化
    lea     di,[di+4]
    inc     argcwrk         ;文字列個数のカウントアップ
nospcloop:
    inc     word ptr ss:[di-2]  ;文字列長さのカウントアップ
    dec     cx
    jcxz    stringend
    inc     bx
    cmp     byte ptr [bx],SPC   ;空白,タブが現れるまでループ
    je      stringend
    cmp     byte ptr [bx],TAB
    je      stringend
    jmp     short nospcloop
stringend:
    mov     byte ptr [bx],0     ;文字列終端に 0 をセット
    inc     bx
    loop    spaceloop       ;空白,タブのスキップ
;
argend:
    mov     ax,argcwrk      ;文字列個数をチェック 0 なら終了
    test    ax,ax
    jnz     argsset
    add     sp,stackwrk
    xor     ax,ax
    ret
;
argsset:
    mov     dx,di           ;文字列情報の最終アドレスをセーブ
    mov     bx,di           ;
    std             ;コピー方向=ダウンカウント
    lea     di,[bp+stackwrk+1]  ;スタック最終アドレスを取得
;   @do until           ;文字列をスタックへコピー
@d0001:
        lea     bx,[bx-4]
        mov     cx,ss:[bx+2]        ;文字列長取得
        mov     ss:[bx+2],ss        ;コピー後セグメントセット
        mov     si,ss:[bx]      ;文字列終端アドレス取得
        add     si,cx
        inc     cx          ;終端文字分をカウントアップ
        mov     es,ss:[bx+2]
      rep   movsb
        mov     ss:[bx],di      ;スタック上の文字列オフセット設定
        inc     word ptr ss:[bx]
        dec     ax
;   @doend (zf,on)
      jnz   @d0001
;                   ;ファーポインタリストのコピー
    and     di,0fffeh       ;コピー先設定
    lea     di,[di-2]
    mov     cx,dx
    mov     si,cx           ;コピー元設定
    lea     si,[si-2]
    sub     cx,bx
    shr     cx,1            ;コピーカウント（ワード）設定
    push    ds
    mov     ds,ss:[si]      ;スタックセグメント取得
  rep    movsw
    pop     ds
;
    mov     ax,argcwrk
    mov     bx,returnaddr       ;リターンアドレス設定
    mov     ss:[di],bx
    lea     bp,[di+2]       ;ファーポインタリストのオフセット
    mov     sp,di
    test    ax,ax
    ret
;
getargs endp
;
;------------------------------------------------------------------------------
;
;   asctoint
;       アスキー10進数字列から、16ビットバイナリーへの変換
;       数字でない文字に出会った時点で終了する
;
;   TYPE    near call
;   IN  es:di アスキー10進数字列アドレス
;   OUT ax 変換した数値
;       es:di 変換時の数字でない文字のアドレス
;   保存レジスタ    bx,cx,dx,si,bp,ds,es
;
;------------------------------------------------------------------------------
;
    public  asctoint
asctoint    proc    uses bx cx dx
;
    xor     ax,ax           ;変換中の数値&変換後通知データ
    mov     cx,ax           ;獲得する(した)文字
    mov     bx,10           ;10進変換のための乗数
;   @do repeat
@d0002:
        mov     cl,es:[di]      ;文字獲得
;       @if (cl,<,'0'),or,(cl,>,'9')
          cmp   cl,'0'
          jb    @i0001
          cmp   cl,'9'
          jbe   @i0002
@i0001:
;           @doexit
              jmp   @d0003
;       @ifend
@i0002:
        and     cl,0fh          ;文字を数値に変換
        mul     bx          ;今までの変換データを10倍
        add     ax,cx           ;獲得した数値を加算
        inc     di          ;次の文字位置へ
;   @doend
      jmp   @d0002
@d0003:
    test    ax,ax           ;ゼロフラグ設定
    ret
;
asctoint    endp
;
;------------------------------------------------------------------------------
;
;   inttoasc0
;       16ビットバイナリをアスキー10進数字列に変換する
;       5 桁固定で 頭の 0 も出力する
;
;   TYPE    near call
;   IN  ax 16ビットバイナリ
;       es:di 変換後のアスキー10進数字列を格納するアドレス
;   OUT es:di 変換したアスキー10進数字列の次のアドレス
;   保存レジスタ    bx,cx,dx,si,bp,ds,es
;
;------------------------------------------------------------------------------
;
    public  inttoasc0
inttoasc0   proc    uses cx dx
;
    cld             ;変換後文字列出力方向 アップ方向
    mov     cx,100          ;10進変換のための除数
    xor     dx,dx           ;32/16ビット除算用の上位16ビットクリア
    div     cx          ;100で割る DX=余り AX=商
    div     cl          ;商を更に100で割る AH=余り AL=商
    add     al,'0'          ;万の位を数字文字に変換して出力
    stosb
    mov     al,ah           ;千,百の位を数字文字に変換して出力
    aam
    add     ax,'00'
    xchg    ah,al
    stosw
    mov     al,dl           ;十,一の位を数字文字に変換して出力
    aam
    add     ax,'00'
    xchg    ah,al
    stosw
    ret
;
inttoasc0   endp
;
;------------------------------------------------------------------------------
;
;   dosstdout
;       MS-DOSのハンドル2番 標準出力へデータを出力する
;       エラーが起こった時はアボートする
;
;   TYPE    near call
;   IN  cx 出力データ長
;       ds:dx 出力データの先頭アドレス
;   OUT なし
;   保存レジスタ    si,di,bp,ds,es
;
;------------------------------------------------------------------------------
;
    public  dosstdout
dosstdout   proc
;
    mov     ah,40h
    mov     bx,1
    int     21h
;   @if (cf,on)
      jnc   @i0003
        mov     ah,4ch
        int     21h
;   @ifend
@i0003:
    ret
;
dosstdout   endp
;
;------------------------------------------------------------------------------
;
;   dosallocx
;       MS-DOSのメモリ獲得を呼び出す、獲得出来ない時は標準出力へエラー
;       メッセージを出力してアボートする
;
;   TYPE    near call
;   IN  dx:ax 獲得したいメモリのバイトサイズ
;   OUT ax 割り当てられたメモリのセグメントアドレス
;   保存レジスタ    cx,si,di,bp,ds,es
;
;------------------------------------------------------------------------------
;
    public  dosallocx
dosallocx    proc   uses bx cx
;
    mov     cl,4
    add     ax,15
    adc     dx,0
    shr     ax,cl
    and     dx,0fh
    ror     dx,cl
    mov     bx,ax
    or      bx,dx
    mov     ah,48h
    int     21h
;   @if (cf,on)
      jnc   @i0004
        mov     errorno,ax
        mov     dx,offset allocmsg
        mov     cx,alcmsgsiz
        jmp     abort
;   @ifend
@i0004:
    ret
;
dosallocx    endp
;
;------------------------------------------------------------------------------
;
;   abort
;       標準出力へメッセージを出力した後、プログラム終了する
;       終了時に終了コードを設定する
;
;   TYPE    near call
;   IN  cx 出力データ長
;       ds(data):dx 出力データの先頭アドレス
;       ds(data):errorno 終了コード
;   OUT なし
;   保存レジスタ    si,di,bp,ds,es
;
;------------------------------------------------------------------------------
;
    public  abort
abort       proc
;
    mov     ax,seg  _data
    mov     ds,ax
    mov     ah,40h
    mov     bx,1
    int     21h
;
    mov     ax,errorno
    mov     ah,4ch
    int     21h
;
abort       endp
;
    end
