home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FM Towns: Free Software Collection 3
/
FREEWARE.BIN
/
ms_dos
/
dsort
/
dstmain.asm
< prev
next >
Wrap
Assembly Source File
|
1980-01-02
|
39KB
|
1,333 lines
page 96,132
;§∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞§
;§ §
;§ ディレクトリエントリ ソート ユーティリティ §
;§ §
;§ DSORT.EXE Ver1.11 §
;§ §
;§ Copyright (C) by 福地 邦雄 1991. All rights reserved. §
;§∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞§
.MODEL SMALL,C
;
DPB struc
drivenumber db ? ;ドライブ番号
unitnumber db ? ;ユニット番号
sectorlength dw ? ;セクタ長
sectorperalloc db ? ;1クラスタ当たりのセクタ数-1
shiftcount db ? ;1クラスタ当たりのセクタ数の2のべき乗
reservedsector dw ? ;先頭のリザーブセクタ数
numberoffat db ? ;FAT数
directoryentry dw ? ;ルートディレクトリのエントリ数
datastartsector dw ? ;データ領域開始セクタ番号
datasector dw ? ;最大クラスタ数(全クラスタ数+1)
fatsector db ? ;1FAT当たりのセクタ数
directorystart dw ? ;ディレクトリ領域開始セクタ番号
todeviceheader dd ? ;デバイスヘッダへのポインタ
mediadescriptor db ? ;メディアディスクリプタ
diskchange db ? ;ディスクの交換可能属性
tonextdpb dd ? ;次のDPBへのポインタ
currentcluster dw ? ;カレントクラスタ
reserved dw ? ;リザーブ
DPB ends
;
YES equ 1
NO equ 0
FAT12 equ 0ff7h
FAT16 equ 0fff7h
direntrysize equ 20h
;
extrn sweep:word,sortexec:word,recursive:word,dirgather:word
extrn dta:dword,srchname:dword,namebuff:dword,namebuffsiz:word
extrn dirtype:word,fattype:word,attribute:word,clustcount:word
extrn driveno:word,clustsize:word,fatsize:word,dirsize:word
extrn fatbuff:word,dirbuff:word,sortbuff:word,sortcount:word
extrn drvinf:byte,clustsect:word,sectcount:word,fatdrive:word
extrn sortfuncs:word,subchain:word,wildcard:byte,pathbuff:byte
extrn usagemsg:byte,entrycount:word,movecount:word,subsearch:word
extrn procs:byte,dirover:byte,fatover:byte,veralarm:byte,_vermsgsz:abs
extrn bothmsg:byte,sortmsg:byte,movemsg:byte,nothmsg:byte
extrn errorno:word,adjustroot:word
;
extrn getargs:near,options:near,usageout:near,abort:near,dosstdout:near
extrn dirlist:near,dirfind:near,strcopywild:near
extrn dosallocx:near,dirqsort:near,inttoasc0:near
;
PUBLIC main,sortproc,getdirinfo,getdpb,readdirectory,readrootdir
PUBLIC readfat,getfat12chain,getfat16chain,readsubdir,selection
PUBLIC remainsweep,copyback,filldeleted,writedirectory,checkrootsize
PUBLIC dspdirname,dspmsgend,altint23h,critical,breakflag,orgint23h
;
.code
;
;------------------------------------------------------------------------------
; 書き込み時のCtrl+C押下によるディレクトリ破壊を防ぐ処理のワーク
;------------------------------------------------------------------------------
;
critical dw NO
breakflag dw NO
orgint23h dd 0
prgname db 'DirSort',0 ; これは別に意味なし
;
;------------------------------------------------------------------------------
;
; main
; ディレクトリエントリソートユーティリティ メインプログラム
;
; dsort <options> directory name
;
; IN ds & es PSP セグメント
; OUT ?
;
;------------------------------------------------------------------------------
;
main proc near
;
call getargs ; コマンド行パラメータを引き数リストに変換
; @if (zf,on)
jnz @i0001
jmp usageout ; 引き数なしの時はヘルプメッセージ
; @ifend
@i0001:
push ax
mov ax,_data ; DS 設定
mov ds,ax
;
mov ah,30h ; DOS バージョンチェック
int 21h
; @if (al,>,3) ; 4.00 以上なら未サポート
cmp al,3
jbe @i0002
mov cx,word ptr _vermsgsz
mov dx,offset veralarm
jmp abort
; @ifend
@i0002:
;
mov ax,1000h ; ディレクトリ名バッファの獲得
xor dx,dx ; 4KB
call dosallocx
mov word ptr namebuff+2,ax
;
mov ax,3523h ; Ctrl+C ベクタ取得
int 21h
mov word ptr cs:orgint23h,bx
mov word ptr cs:orgint23h+2,es
mov bx,ds ; DS セーブ
mov es,bx
mov ax,2523h ; Ctrl+C ベクタ置き換え
mov dx,offset altint23h ;
mov bx,cs
mov ds,bx
int 21h
mov bx,es ; DS リストア
mov ds,bx
pop ax
;
call options ; 引き数評価&対象ディレクトリリスト作成
; @if (sortexec,/=,NO),or,(sweep,/=,NO)
cmp sortexec,NO
jne @i0003
cmp sweep,NO
je @i0004
@i0003:
; @if (recursive,=,YES) ; 再帰呼び出しをおこなうか?
cmp recursive,YES
jne @i0005
mov es,word ptr namebuff+2
mov bx,800h ; ディレクトリ名バッファのサイズ変更
mov ah,4ah ; 16KB
int 21h
; @if (cf,off)
jc @i0006
add namebuffsiz,7000h
; @ifend
@i0006:
; @ifend
@i0005:
push namebuffsiz ; パラメータセット
push word ptr namebuff
push word ptr namebuff+2
xor ax,ax
push ax
call sortproc ; ディレクトリソート実行
; @ifend
@i0004:
;
mov ax,2523h ; Ctrl+C ベクタ復元
lds dx,cs:orgint23h
int 21h
;
mov ah,0dh ; ディスクバッファ リセット
int 21h
;
mov ax,4c00h ; プログラム終了
int 21h
;
main endp
;
;------------------------------------------------------------------------------
;
; sortproc
; ディレクトリソートを実行する
;
; TYPE near call
; IN sp+2:ディレクトリ名リストアドレス
; sp+6:ディレクトリ名バッファの空き領域の先頭
; sp+8:ディレクトリ名バッファの空き領域サイズ
; OUT なし
; 保存レジスタ ds
;
;------------------------------------------------------------------------------
;
sortproc proc near curnameoff,curnameseg,freenameoff,freenamesiz
;
mov di,curnameoff
mov es,curnameseg
; @do until
@d0001:
mov entrycount,0 ; 処理したエントリのカウンタを初期化
mov sortcount,0
mov movecount,0
mov ah,0dh ; ディスクバッファ リセット
int 21h
;
call getdirinfo ; ディレクトリ情報獲得
; @if (zf,on),L
jz @i0007
jmp @i0008
@i0007:
mov di,curnameoff ; ディレクトリ名表示
mov es,curnameseg
call dspdirname
call readdirectory ; ディレクトリ読み込み
; @if (zf,on)
jnz @i0009
; @if (sortexec,=,YES),S
cmp sortexec,YES
jne @i0010
call selection ; ソート対象エントリ取り出し
; @if (ax,>,1)
cmp ax,1
jbe @i0011
push ds
mov ax,ds
mov es,ax
mov ax,offset sortfuncs
push ax
push sortcount
xor ax,ax
push ax
mov ds,sortbuff
call dirqsort ; クイックソート
pop ds
; @ifend
@i0011:
; @if (sweep,=,YES)
cmp sweep,YES
jne @i0012
call remainsweep ; ソート対象外エントリを掻き集める
; @ifend
@i0012:
call copyback ; ソートしたエントリを戻す
; @else
jmp short @i0013
@i0010:
call predelete
call remainsweep
; @ifend
@i0013:
call filldeleted ; 削除エントリの情報をクリアする
mov cs:critical,YES ; クリティカルセクション開始
call writedirectory ; ディレクトリ書き込み
call dspmsgend ; 終了メッセージ表示
mov cs:critical,NO ; クリティカルセクション終了
; @if (cs:breakflag,=,YES) ; Ctrl+Cが押下されたので終了
cmp cs:breakflag,YES
jne @i0014
mov errorno,-1
xor cx,cx
xor dx,dx
jmp abort
; @ifend
@i0014:
; @ifend
@i0009:
; @if (recursive,=,YES) ; 再帰呼び出し
cmp recursive,YES
jne @i0015
mov ah,0dh ; ディスクバッファ リセット
int 21h
;
mov subsearch,YES ;
mov di,curnameoff ; サブディレクトリのリスト獲得
mov es,curnameseg
call strcopywild
mov word ptr srchname,di
mov word ptr srchname+2,es
call dirlist
mov ax,word ptr namebuff
; @if (ax,/=,freenameoff) ; サブディレクトリ有りの時
cmp ax,freenameoff
je @i0016
push namebuffsiz
push ax
push word ptr namebuff+2
push freenameoff
call sortproc ; ディレクトリソート再帰実行
; @ifend
@i0016:
mov si,freenameoff ; 各ワーク情報を再帰実行から戻す
mov es,freenamesiz
mov namebuffsiz,es
mov word ptr namebuff,si
mov es,curnameseg
mov word ptr es:[si],0
mov subsearch,NO ;
; @ifend
@i0015:
; @ifend
@i0008:
mov di,curnameoff ; 次の対象ディレクトリへ
mov es,curnameseg
cld
xor ax,ax
mov cx,-1
repne scasb
mov curnameoff,di
; @doend (byte ptr es:[di],=,0),L ; ディレクトリリストの終了か?
cmp byte ptr es:[di],0
je @d0002
jmp @d0001
@d0002:
;
ret 8
;
sortproc endp
;
;------------------------------------------------------------------------------
;
; getdirinfo
; ディレクトリ及びその所属するドライブの情報を獲得する
;
; TYPE near call
; IN ds:di = ディレクトリ名
; OUT drvinf = DPBのコピー その他 ディレクトリ情報
; 保存レジスタ bx,cx,dx,si,di,bp,ds,es
;
;------------------------------------------------------------------------------
;
getdirinfo proc near
;
call dirfind
; @if (zf,on)
jnz @i0017
mov dirtype,ax ; ディレクトリタイプ ルート/サブ
mov subchain,ax ; FATチェインの先頭
mov driveno,dx ; ドライブ番号
dec driveno
;
mov di,offset drvinf ; Drive Parameter Block 取得
call getdpb
;
; @if (drvinf.datasector,<=,4086),S ; 12bitFAT/16bitFAT
cmp drvinf.datasector,4086
ja @i0018
mov fattype,FAT12 ; v1.00バグ '='が無かった
; @else
jmp short @i0019
@i0018:
mov fattype,FAT16
; @ifend
@i0019:
xor ax,ax
mov al,drvinf.sectorperalloc
inc ax
mov clustsect,ax ; 1クラスタ当たりのセクタ数
mul drvinf.sectorlength
mov clustsize,ax ; 1クラスタのバイトサイズ
xor ax,ax
; @ifend
@i0017:
ret
;
getdirinfo endp
;
;------------------------------------------------------------------------------
;
; getdpb
; ドライブパラメータブロックをコピーする
;
; TYPE near call
; IN dl = ドライブ番号 A:1 B:2 ...
; ds:di = drive parameter block をコピーする領域のアドレス
; OUT ax = 完了コード
; 保存レジスタ bx,cx,dx,si,di,bp,ds,es
;
;------------------------------------------------------------------------------
;
getdpb proc near uses bx cx si di ds es
;
cld
mov ax,ds
mov es,ax
mov ah,32h ; DPBアドレス取得 非公開
mov cx,10h
int 21h
;
mov si,bx
rep movsw ; DPB コピー
ret
;
getdpb endp
;
;------------------------------------------------------------------------------
;
; readdirectory
; ディレクトリを読み込む
;
; TYPE near call
; IN dirtype,driveno,drvinf構造体,fatdrive
; OUT ax = 完了コード entrycount,clustcount
; 保存レジスタ bx,cx,dx,si,di,bp,ds,es
;
;------------------------------------------------------------------------------
;
readdirectory proc near
;
; @if (dirtype,=,0),S ; ルートディレクトリ
cmp dirtype,0
jne @i0020
mov ax,drvinf.directoryentry
; @if (ax,<=,2048),S
cmp ax,2048
ja @i0021
mov entrycount,ax ; ディレクトリエントリ数 格納
mov adjustroot,NO
call readrootdir
; @else
jmp short @i0022
@i0021:
mov entrycount,2048 ; ディレクトリエントリ数を2048とする
mov adjustroot,YES ; ルートのエントリ数評価を遅らせる
call readrootdir
call checkrootsize ; エントリ数評価
; @if (zf,off)
jz @i0023
mov ah,9 ; ルートディレクトリサイズオーバー表示
mov dx,offset dirover
int 21h
mov ax,-1
jmp rdirerror
; @ifend
@i0023:
; @ifend
@i0022:
; @else
jmp short @i0024
@i0020:
mov ax,driveno ; サブディレクトリ
; @if (ax,/=,fatdrive) ; 読み込み済FATと違うドライブ名の時
cmp ax,fatdrive
je @i0025
xor ax,ax ; FATサイズ計算
mov al,drvinf.fatsector
mul drvinf.sectorlength
; @if (dx,=,1),and,(ax,=,0),or,(dx,=,0),S
cmp dx,1
jne @i0026
or ax,ax
je @i0027
@i0026:
or dx,dx
jne @i0028
@i0027:
call readfat ; FAT読み込み
; @else
jmp short @i0029
@i0028:
mov ah,9 ; FATサイズオーバー表示
mov dx,offset fatover
int 21h
mov ax,-1
jmp rdirerror
; @ifend
@i0029:
; @ifend
@i0025:
;
cld ; サブディレクトリのクラスタチェインを獲得
mov di,offset subchain
mov es,fatbuff
; @if (fattype,=,FAT12),S
cmp fattype,FAT12
jne @i0030
call getfat12chain
; @else
jmp short @i0031
@i0030:
call getfat16chain
; @ifend
@i0031:
mov clustcount,dx ; サブディレクトリのクラスタ数を設定
mov ax,dx
mul clustsize
mov cx,32 ; ディレクトリエントリ数 計算 格納
div cx
; @if (ax,<=,2048),S
cmp ax,2048
ja @i0032
mov entrycount,ax
call readsubdir ; サブディレクトリ読み込み
; @else
jmp short @i0033
@i0032:
mov ah,9 ; ディレクトリサイズオーバー表示
mov dx,offset dirover
int 21h
mov ax,-1
; @ifend
@i0033:
; @ifend
@i0024:
rdirerror:
test ax,ax
ret
;
readdirectory endp
;
;------------------------------------------------------------------------------
;
; readrootdir
; ルートディレクトリの内容をメモリに読み込む
;
; TYPE near call
; IN drive parameter block 領域 adjustroot
; OUT dirbuff = 読み込んだディレクトリのセグメントアドレス
; 保存レジスタ bp,ds,es
;
;------------------------------------------------------------------------------
;
readrootdir proc near uses bp
;
; @if (adjustroot,=,NO),S
cmp adjustroot,NO
jne @i0034
mov ax,drvinf.datastartsector ; ディレクトリサイズ計算とメモリ獲得
sub ax,drvinf.directorystart
; @else
jmp short @i0035
@i0034:
xor ax,ax ; ルートディレクトリが2048を超えて
mov dx,1 ; いる場合の暫定措置
div drvinf.sectorlength
; @ifend
@i0035:
mov sectcount,ax
mul drvinf.sectorlength
mov dirsize,ax
call dosallocx
mov dirbuff,ax
;
push ds ; ルートディレクトリ読み込み
mov ax,driveno
xor bx,bx
mov cx,sectcount
mov dx,drvinf.directorystart
mov ds,dirbuff
int 25h
; @if (cf,on)
jnc @i0036
xor cx,cx
xor dx,dx
jmp abort
; @ifend
@i0036:
popf
pop ds
xor ax,ax
ret
;
readrootdir endp
;
;------------------------------------------------------------------------------
;
; checkrootsize
; ルートディレクトリのエントリ数をチェックする
;
; TYPE near call
; IN dirbuff = 読み込んだディレクトリのセグメントアドレス
; OUT ax = 0 ディレクトリ数が範囲内 ax /= 0 範囲オーバー
; 保存レジスタ bx,cx,dx,si,di,bp,ds,es
;
;------------------------------------------------------------------------------
;
checkrootsize proc near uses di es
;
xor di,di ; オフセットを0
mov es,dirbuff ; ディレクトリバッファセグメントを取得
; @do until
@d0003:
; @if (byte ptr es:[di],=,0) ; 最終エントリを発見したかの判定
cmp byte ptr es:[di],0
jne @i0037
xor ax,ax ; 有効+削除エントリが64KB未満(範囲内)
jmp chrtszfind
; @ifend
@i0037:
lea di,[di+direntrysize] ; 次のエントリへ
; @doend (di,=,0) ; 64KBひとまわりしたか?
or di,di
jne @d0003
mov ax,-1 ; 扱える範囲を超えている
chrtszfind:
test ax,ax
ret
;
checkrootsize endp
;
;------------------------------------------------------------------------------
;
; readfat
; FATを読み込むための領域を獲得し、FATを読み込む
;
; TYPE near call
; IN drive parameter block 領域
; OUT fatbuff = 読み込んだFATのセグメントアドレス
; 保存レジスタ bp,ds,es
;
;------------------------------------------------------------------------------
;
readfat proc near uses bp
;
; @if (fatdrive,/=,-1) ; 既に別のFATを読み込み済の時、解放する
cmp fatdrive,-1
je @i0038
mov es,fatbuff
int 21h
mov fatdrive,-1
mov fatbuff,0
; @ifend
@i0038:
xor ax,ax ; FAT用領域獲得
mov al,drvinf.fatsector
mul drvinf.sectorlength
call dosallocx
mov fatbuff,ax
;
push ds ; FAT読み込み
mov ax,driveno
mov fatdrive,ax
xor bx,bx
xor cx,cx
mov cl,drvinf.fatsector
mov dx,drvinf.reservedsector
mov ds,fatbuff
int 25h
; @if (cf,on)
jnc @i0039
xor cx,cx
xor dx,dx
jmp abort
; @ifend
@i0039:
popf
pop ds
ret
;
readfat endp
;
;------------------------------------------------------------------------------
;
; getfat12chain
; 12ビットFATのチェインをたどって、配列に書き出す。
;
; TYPE near call
; IN es:オフセット0= FAT領域
; ds:di = FATチェインを書き出す配列、 及びその先頭に最初のクラスタ
; 番号を格納しておくこと
; OUT dx = チェインの総クラスタ数
; 保存レジスタ si,bp,ds,es
;
;------------------------------------------------------------------------------
;
getfat12chain proc near
;
mov cl,4
xor dx,dx
; @do while,(word ptr [di],<,FAT12)
@d0004:
cmp word ptr [di],FAT12
jae @d0005
mov bx,[di]
mov ax,bx
shr ax,1
add bx,ax
mov ax,es:[bx]
; @if (word ptr [di],off,1),S
test word ptr [di],1
jnz @i0040
and ax,0fffh
; @else
jmp short @i0041
@i0040:
shr ax,cl
; @ifend
@i0041:
lea di,[di+2]
mov [di],ax
inc dx
; @doend
jmp @d0004
@d0005:
ret
;
getfat12chain endp
;
;------------------------------------------------------------------------------
;
; getfat16chain
; 16ビットFATのチェインをたどって、配列に書き出す。
;
; TYPE near call
; IN es:オフセット0 = FAT領域
; ds:di = FATチェインを書き出す配列、 及びその先頭に最初のクラスタ
; 番号を格納しておくこと
; OUT dx = チェインの総クラスタ数
; 保存レジスタ cx,si,bp,ds,es
;
;------------------------------------------------------------------------------
;
getfat16chain proc near
;
xor dx,dx
; @do while,(word ptr [di],<,FAT16)
@d0006:
cmp word ptr [di],FAT16
jae @d0007
mov bx,[di]
shl bx,1
mov ax,es:[bx]
lea di,[di+2]
mov [di],ax
inc dx
; @doend
jmp @d0006
@d0007:
ret
;
getfat16chain endp
;
;------------------------------------------------------------------------------
;
; readsubdir
; サブディレクトリを読み込む
;
; TYPE near call
; IN clustcount ディレクトリのクラスタ数
; OUT dirbuff = 読み込んだディレクトリのセグメントアドレス
; 保存レジスタ cx,si,bp,ds,es
;
;------------------------------------------------------------------------------
;
readsubdir proc near
local cluster:word
;
mov dx,clustcount ; ディレクトリサイズ計算
mov cluster,dx
mov ax,clustsect
mul dx
mul drvinf.sectorlength
mov dirsize,ax
call dosallocx ; ディレクトリバッファ獲得
mov dirbuff,ax
xor bx,bx
mov di,offset subchain ; ディレクトリクラスタチェインの先頭
;
push ds
mov ax,ds
mov es,ax
mov ds,dirbuff
; @do until
@d0008:
mov ax,es:[di] ; ディレクトリクラスタ読み込み
sub ax,2
mov cx,es:clustsect
mul cx
add ax,es:drvinf.datastartsector
mov dx,ax
mov ax,es:driveno
push bp
push di
int 25h
; @if (cf,on)
jnc @i0042
xor cx,cx
xor dx,dx
jmp abort
; @ifend
@i0042:
popf
pop di
pop bp
add bx,es:clustsize ; 次のバッファオフセット
lea di,[di+2] ; 次のクラスタ
dec cluster ; カウントダウン
; @doend (zf,on)
jnz @d0008
pop ds
xor ax,ax
ret
;
readsubdir endp
;
;------------------------------------------------------------------------------
;
; selection
; 読み込んだディレクトリからattributeで指定されたエントリを選択して
; ソートバッファに移動する
;
; TYPE near call
; IN dirbuff = 読み込んだディレクトリのセグメントアドレス その他
; OUT sortbuff = ソート対象を選択・移動したセグメントアドレス
; 保存レジスタ bp,ds
;
;------------------------------------------------------------------------------
;
selection proc near
;
mov ax,dirsize ; ディレクトリサイズからバッファサイズ
; @if (ax,/=,0),S ; 64KB未満
or ax,ax
je @i0043
xor dx,dx
; @else ; 64KB
jmp short @i0044
@i0043:
mov dx,1
; @ifend
@i0044:
call dosallocx ; ソートバッファ獲得
mov sortbuff,ax
mov es,ax
mov bx,attribute ; 選出属性
mov dx,entrycount ; エントリ数
xor si,si
xor di,di
; @if (dirtype,/=,0) ; サブディレクトリの時は最初の2つを除外
cmp dirtype,0
je @i0045
sub dx,2
mov si,64
; @ifend
@i0045:
;
push ds
cld
xor ax,ax
mov ds,dirbuff
; @do while,(dx,/=,0),and,(byte ptr [si],/=,0)
@d0009:
or dx,dx
je @d0010
cmp byte ptr [si],0
je @d0010
; @cbegin
; @case (byte ptr [si],=,0e5h),S ; 削除エントリか?
cmp byte ptr [si],0e5h
jne @c0002
mov byte ptr [si],0 ; 後の処理のために0を書いておく
lea si,[si+20h]
; @case (byte ptr [si+0bh],on,bl),S ; 属性違いか?
jmp short @c0001
@c0002:
test byte ptr [si+0bh],bl
jz @c0003
lea si,[si+20h]
; @other ; ソートバッファへ移動
jmp short @c0001
@c0003:
mov cx,10h
rep movsw
mov byte ptr [si-20h],0 ; 移動元に0を書いておく
; @if (byte ptr [di-20h],=,5) ; 名前の頭がE5用のコードなら戻しておく
cmp byte ptr [di-20h],5
jne @i0046
mov byte ptr [di-20h],0e5h
; @ifend
@i0046:
inc ax ; 移動したエントリ数を加算
; @cend
@c0001:
dec dx ; カウントダウン
; @doend
jmp @d0009
@d0010:
pop ds
mov sortcount,ax ; 移動したエントリ数を記録
ret
;
selection endp
;
;------------------------------------------------------------------------------
;
; predelete
; 後のremainsweepルーチンのために削除エントリの先頭を00とする
;
; TYPE near call
; IN entrycount,dirbuff
; OUT なし
; 保存レジスタ ax,bx,dx,si,bp,ds
;
;------------------------------------------------------------------------------
;
predelete proc near
;
mov cx,entrycount
xor di,di
mov es,dirbuff
; @do until
@d0011:
; @if (byte ptr es:[di],=,0e5h)
cmp byte ptr es:[di],0e5h
jne @i0047
mov byte ptr es:[di],0
; @ifend
@i0047:
lea di,[di+20h]
dec cx
; @doend (zf,on)
jnz @d0011
ret
;
predelete endp
;
;------------------------------------------------------------------------------
;
; remainsweep
; ソート対象外のエントリをディレクトリバッファの先頭に集める
;
; TYPE near call
; IN entrycount,dirbuff
; OUT movecount
; 保存レジスタ ax,bp,ds
;
;------------------------------------------------------------------------------
;
remainsweep proc near
;
cld
push ds
xor bx,bx
mov dx,entrycount ; ディレクトリのエントリサイズ
mov es,dirbuff
mov ds,dirbuff
xor di,di
; @do while,(byte ptr [di],/=,0),and,(dx,/=,0) ; 最初の空きエントリ位置取得
@d0012:
cmp byte ptr [di],0
je @d0013
or dx,dx
je @d0013
lea di,[di+20h]
dec dx
; @doend
jmp @d0012
@d0013:
mov si,di
; @do until
@d0014:
; @do while,(byte ptr [si],=,0),and,(dx,/=,0) ; 次の有効エントリ位置取得
@d0015:
cmp byte ptr [si],0
jne @d0016
or dx,dx
je @d0016
lea si,[si+20h]
dec dx
; @doend
jmp @d0015
@d0016:
; @if (dx,/=,0) ; 終了でなければエントリを頭へ詰める
or dx,dx
je @i0048
inc bx
mov cx,10h
rep movsw
mov byte ptr [si-20h],0 ; 移動元を空きエントリとする
dec dx ; カウントダウン
; @do while,(byte ptr [di],/=,0) ; 次の空きエントリ位置取得
@d0017:
cmp byte ptr [di],0
je @d0018
lea di,[di+20h]
; @doend
jmp @d0017
@d0018:
; @ifend
@i0048:
; @doend (dx,=,0)
or dx,dx
jne @d0014
pop ds
mov movecount,bx ; 移動したエントリ数を記録
ret
;
remainsweep endp
;
;------------------------------------------------------------------------------
;
; copyback
; ソートバッファの内容をディレクトリバッファへ書き戻す
;
; TYPE near call
; IN sortcount,sortbuff,dirbuff
; OUT dirbuff
; 保存レジスタ bx,bp,ds
;
;------------------------------------------------------------------------------
;
copyback proc near uses ds
;
cld
mov dx,sortcount ; ソートバッファ上のエントリ数
mov es,dirbuff
mov ds,sortbuff
xor si,si
xor di,di
; @do while,(dx,/=,0)
@d0019:
or dx,dx
je @d0020
; @if (byte ptr es:[di],=,0),S ; ディレクトリバッファは空きエントリ?
cmp byte ptr es:[di],0
jne @i0049
; @if (byte ptr [si],=,0e5h) ; 名前の頭がE5なら、変換しておく
cmp byte ptr [si],0e5h
jne @i0050
mov byte ptr [si],05h
; @ifend
@i0050:
mov cx,10h ; コピー
rep movsw
dec dx ; カウントダウン
; @else
jmp short @i0051
@i0049:
lea di,[di+20h] ; 次のディレクトリバッファエントリへ
; @ifend
@i0051:
; @doend
jmp @d0019
@d0020:
;
mov ax,ds ; ソートバッファの解放
mov es,ax
mov ah,49h
int 21h
;
ret
;
copyback endp
;
;------------------------------------------------------------------------------
;
; filldeleted
; ディレクトリ中の削除エントリをクリアする
;
; TYPE near call
; IN dirsize,dirbuff
; OUT なし
; 保存レジスタ bx,dx,bp,ds
;
;------------------------------------------------------------------------------
;
filldeleted proc near
;
cld
mov ax,0f6h ; 埋め込みデータの設定
mov si,dirsize ; ディレクトリの最終ポイント取得
mov es,dirbuff
; @do until
@d0021:
lea si,[si-20h] ; 最終位置から先頭方向へ
; @if (byte ptr es:[si],=,0),S ; 削除エントリ判定
cmp byte ptr es:[si],0
jne @i0052
mov es:[si],ah ; 頭1バイト 0orE5
mov cx,1fh ; 残り31バイトをF6で埋める
lea di,[si+1]
rep stosb
; @else ; 有効エントリが見つかったので
jmp short @i0053
@i0052:
mov ah,0e5h ; それ以後は頭1バイトをE5に変更
; @ifend
@i0053:
; @doend (si,=,0) ; ディレクトリ先頭になるまで
or si,si
jne @d0021
ret
;
filldeleted endp
;
;------------------------------------------------------------------------------
;
; writedirectory
; ディレクトリバッファをファイルに書き戻す
;
; TYPE near call
; IN dirtype,driveno,drvinf構造体,sectcount,clustcount,dirbuff
; clustsect,clustsize,subchain
; OUT なし
; 保存レジスタ
;
;------------------------------------------------------------------------------
;
writedirectory proc near
local cluster:word
;
; @if (dirtype,=,0),S
cmp dirtype,0
jne @i0054
push ds ; ルートディレクトリ書き込み
mov ax,driveno
xor bx,bx
mov cx,sectcount
mov dx,drvinf.directorystart
mov ds,dirbuff
push bp
int 26h
; @if (cf,on)
jnc @i0055
xor cx,cx
xor dx,dx
jmp abort
; @ifend
@i0055:
popf
pop bp
pop ds
; @else
jmp short @i0056
@i0054:
push ds ; サブディレクトリ書き込み
mov ax,clustcount
mov cluster,ax
mov di,offset subchain
mov ax,ds
mov es,ax
xor bx,bx
mov ds,dirbuff
; @do until
@d0022:
mov ax,es:[di]
sub ax,2
mov cx,es:clustsect
mul cx
add ax,es:drvinf.datastartsector
mov dx,ax
mov ax,es:driveno
push bp
push di
int 26h
; @if (cf,on)
jnc @i0057
xor cx,cx
xor dx,dx
jmp abort
; @ifend
@i0057:
popf
pop di
pop bp
add bx,es:clustsize
lea di,[di+2]
dec cluster
; @doend (zf,on)
jnz @d0022
pop ds
; @ifend
@i0056:
;
mov es,dirbuff ; ソートバッファの開放
mov ah,49h
int 21h
;
ret
;
writedirectory endp
;
;------------------------------------------------------------------------------
;
; dspdirname
; 処理中ディレクトリ名を表示する
;
; TYPE near call
; IN ES:DI ディレクトリ名文字列アドレス
; OUT なし
; 保存レジスタ DS
;
;------------------------------------------------------------------------------
;
dspdirname proc
;
mov ah,9 ; 処理中メッセージ表示
mov dx,offset procs
int 21h
;
cld ; ディレクトリ名長さを獲得
mov cx,-1
xor ax,ax
mov dx,di
repne scasb
not cx
dec cx
;
push ds ; ディレクトリ名表示
mov ax,es
mov ds,ax
call dosstdout
pop ds
;
mov ah,2 ; 行頭への復帰
mov dl,0dh
int 21h
;
ret
;
dspdirname endp
;
;------------------------------------------------------------------------------
;
; dspmsgend
; 処理終了メッセージを表示する
;
; TYPE near call
; IN sortcount,movecount,sortproc,sweep
; OUT なし
; 保存レジスタ ax,bx,cx,dx,si,di,bp,ds,es
;
;------------------------------------------------------------------------------
;
dspmsgend proc uses ax bx cx dx si di ds es
local wrks:dword,wrka:word
;
mov ax,sortcount ; ソートしたエントリ数
mov bx,movecount ; 移動したエントリ数
mov cx,ax
add cx,bx
; @cbegin
; @case (sortexec,=,YES),and,(sweep,=,YES),and,(cx,/=,0),S ; ソート&移動
cmp sortexec,YES
jne @c0005
cmp sweep,YES
jne @c0005
or cx,cx
je @c0005
mov ax,cx
mov si,offset bothmsg
; @case (sortexec,=,YES),and,(sweep,=,NO),and,(ax,/=,0),S ; ソートのみ
jmp short @c0004
@c0005:
cmp sortexec,YES
jne @c0006
cmp sweep,NO
jne @c0006
or ax,ax
je @c0006
; @if (ax,>,1),S
cmp ax,1
jbe @i0058
mov si,offset sortmsg ; 2つ以上ならソートのみ表示
; @else
jmp short @i0059
@i0058:
mov si,offset bothmsg ; 1つだけならソート&移動表示
; @ifend
@i0059:
; @case (sortexec,=,NO),and,(sweep,=,YES),and,(bx,/=,0),S ; 移動のみ
jmp short @c0004
@c0006:
cmp sortexec,NO
jne @c0007
cmp sweep,YES
jne @c0007
or bx,bx
je @c0007
mov ax,cx
mov si,offset movemsg ; 移動
; @other
jmp short @c0004
@c0007:
xor ax,ax
mov si,offset nothmsg ; 対象なし
; @cend
@c0004:
; @if (ax,/=,0)
or ax,ax
je @i0060
mov di,ss ; 処理したエントリ数表示
mov es,di
lea di,offset wrka+1
call inttoasc0
lea di,[di-5] ; 0サプレス処理
push di
mov cx,4
; @do while,(byte ptr es:[di],=,'0'),and,(cx,/=,0)
@d0023:
cmp byte ptr es:[di],'0'
jne @d0024
or cx,cx
je @d0024
mov byte ptr es:[di],' '
inc di
dec cx
; @doend
jmp @d0023
@d0024:
mov cx,5 ; エントリ数表示
pop dx
mov di,ds
push ss
pop ds
call dosstdout
mov ds,di
; @ifend
@i0060:
mov ah,9 ; エントリ数に続くメッセージ表示
mov dx,si
int 21h
ret
;
dspmsgend endp
;
;------------------------------------------------------------------------------
;
; altint23h
; Ctrl+C押下の横取り
;
; TYPE interrupt
; IN なし
; OUT なし
; 保存レジスタ ax,bx,cx,dx,si,di,bp,ds,es
;
;------------------------------------------------------------------------------
;
altint23h proc
;
; @if (cs:critical,=,NO),S ; クリティカルセクションではない時
cmp cs:critical,NO
jne @i0061
jmp cs:orgint23h ; 既存の終了処理へ
; @else ; クリティカルセクションの時
jmp short @i0062
@i0061:
mov cs:breakflag,YES ; Ctrl+C押下を記憶しただけで復帰
iret
; @ifend
@i0062:
;
altint23h endp
;
end main