home *** CD-ROM | disk | FTP | other *** search
/ FM Towns: Free Software Collection 3 / FREEWARE.BIN / ms_dos / dsort / dstmain.asm < prev    next >
Assembly Source File  |  1980-01-02  |  39KB  |  1,333 lines

  1.     page    96,132
  2. ;§∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞§
  3. ;§                                                                          §
  4. ;§              ディレクトリエントリ  ソート  ユーティリティ                §
  5. ;§                                                                          §
  6. ;§                                     DSORT.EXE  Ver1.11    §
  7. ;§                                                                          §
  8. ;§                   Copyright (C) by 福地 邦雄 1991. All rights reserved.  §
  9. ;§∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞§
  10.     .MODEL  SMALL,C
  11. ;
  12.     DPB struc
  13. drivenumber     db      ?       ;ドライブ番号
  14. unitnumber      db      ?       ;ユニット番号
  15. sectorlength    dw      ?       ;セクタ長
  16. sectorperalloc  db      ?       ;1クラスタ当たりのセクタ数-1
  17. shiftcount      db      ?       ;1クラスタ当たりのセクタ数の2のべき乗
  18. reservedsector  dw      ?       ;先頭のリザーブセクタ数
  19. numberoffat     db      ?       ;FAT数
  20. directoryentry  dw      ?       ;ルートディレクトリのエントリ数
  21. datastartsector dw      ?       ;データ領域開始セクタ番号
  22. datasector      dw      ?       ;最大クラスタ数(全クラスタ数+1)
  23. fatsector       db      ?       ;1FAT当たりのセクタ数
  24. directorystart  dw      ?       ;ディレクトリ領域開始セクタ番号
  25. todeviceheader  dd      ?       ;デバイスヘッダへのポインタ
  26. mediadescriptor db      ?       ;メディアディスクリプタ
  27. diskchange      db      ?       ;ディスクの交換可能属性
  28. tonextdpb       dd      ?       ;次のDPBへのポインタ
  29. currentcluster  dw      ?       ;カレントクラスタ
  30. reserved        dw      ?       ;リザーブ
  31.     DPB ends
  32. ;
  33. YES     equ     1
  34. NO      equ     0
  35. FAT12   equ     0ff7h
  36. FAT16   equ     0fff7h
  37. direntrysize    equ 20h
  38. ;
  39.     extrn   sweep:word,sortexec:word,recursive:word,dirgather:word
  40.     extrn   dta:dword,srchname:dword,namebuff:dword,namebuffsiz:word
  41.     extrn   dirtype:word,fattype:word,attribute:word,clustcount:word
  42.     extrn   driveno:word,clustsize:word,fatsize:word,dirsize:word
  43.     extrn   fatbuff:word,dirbuff:word,sortbuff:word,sortcount:word
  44.     extrn   drvinf:byte,clustsect:word,sectcount:word,fatdrive:word
  45.     extrn   sortfuncs:word,subchain:word,wildcard:byte,pathbuff:byte
  46.     extrn   usagemsg:byte,entrycount:word,movecount:word,subsearch:word
  47.     extrn   procs:byte,dirover:byte,fatover:byte,veralarm:byte,_vermsgsz:abs
  48.     extrn   bothmsg:byte,sortmsg:byte,movemsg:byte,nothmsg:byte
  49.     extrn   errorno:word,adjustroot:word
  50. ;
  51.     extrn   getargs:near,options:near,usageout:near,abort:near,dosstdout:near
  52.     extrn   dirlist:near,dirfind:near,strcopywild:near
  53.     extrn   dosallocx:near,dirqsort:near,inttoasc0:near
  54. ;
  55.     PUBLIC  main,sortproc,getdirinfo,getdpb,readdirectory,readrootdir
  56.     PUBLIC  readfat,getfat12chain,getfat16chain,readsubdir,selection
  57.     PUBLIC  remainsweep,copyback,filldeleted,writedirectory,checkrootsize
  58.     PUBLIC  dspdirname,dspmsgend,altint23h,critical,breakflag,orgint23h
  59. ;
  60.     .code
  61. ;
  62. ;------------------------------------------------------------------------------
  63. ;   書き込み時のCtrl+C押下によるディレクトリ破壊を防ぐ処理のワーク
  64. ;------------------------------------------------------------------------------
  65. ;
  66. critical    dw  NO
  67. breakflag   dw  NO
  68. orgint23h   dd  0
  69. prgname     db  'DirSort',0     ; これは別に意味なし
  70. ;
  71. ;------------------------------------------------------------------------------
  72. ;
  73. ;   main
  74. ;       ディレクトリエントリソートユーティリティ メインプログラム
  75. ;
  76. ;   dsort   <options>   directory name
  77. ;
  78. ;   IN      ds & es PSP セグメント
  79. ;   OUT     ?
  80. ;
  81. ;------------------------------------------------------------------------------
  82. ;
  83. main        proc    near
  84. ;
  85.     call    getargs                 ; コマンド行パラメータを引き数リストに変換
  86. ;   @if (zf,on)
  87.       jnz   @i0001
  88.         jmp     usageout            ; 引き数なしの時はヘルプメッセージ
  89. ;   @ifend
  90. @i0001:
  91.     push    ax
  92.     mov     ax,_data                ; DS 設定
  93.     mov     ds,ax
  94. ;
  95.     mov     ah,30h                  ; DOS バージョンチェック
  96.     int     21h
  97. ;   @if (al,>,3)                    ; 4.00 以上なら未サポート
  98.       cmp   al,3
  99.       jbe   @i0002
  100.         mov     cx,word ptr _vermsgsz
  101.         mov     dx,offset veralarm
  102.         jmp     abort
  103. ;   @ifend
  104. @i0002:
  105. ;
  106.     mov     ax,1000h                ; ディレクトリ名バッファの獲得
  107.     xor     dx,dx                   ; 4KB
  108.     call    dosallocx
  109.     mov     word ptr namebuff+2,ax
  110. ;
  111.     mov     ax,3523h                ; Ctrl+C ベクタ取得
  112.     int     21h
  113.     mov     word ptr cs:orgint23h,bx
  114.     mov     word ptr cs:orgint23h+2,es
  115.     mov     bx,ds                   ; DS セーブ
  116.     mov     es,bx
  117.     mov     ax,2523h                ; Ctrl+C ベクタ置き換え
  118.     mov     dx,offset altint23h     ;
  119.     mov     bx,cs
  120.     mov     ds,bx
  121.     int     21h
  122.     mov     bx,es                   ; DS リストア
  123.     mov     ds,bx
  124.     pop     ax
  125. ;
  126.     call    options                 ; 引き数評価&対象ディレクトリリスト作成
  127. ;   @if (sortexec,/=,NO),or,(sweep,/=,NO)
  128.       cmp   sortexec,NO
  129.       jne   @i0003
  130.       cmp   sweep,NO
  131.       je    @i0004
  132. @i0003:
  133. ;       @if (recursive,=,YES)       ; 再帰呼び出しをおこなうか?
  134.           cmp   recursive,YES
  135.           jne   @i0005
  136.             mov     es,word ptr namebuff+2
  137.             mov     bx,800h         ; ディレクトリ名バッファのサイズ変更
  138.             mov     ah,4ah          ; 16KB
  139.             int     21h
  140. ;           @if (cf,off)
  141.               jc    @i0006
  142.                 add     namebuffsiz,7000h
  143. ;           @ifend
  144. @i0006:
  145. ;       @ifend
  146. @i0005:
  147.         push    namebuffsiz         ; パラメータセット
  148.         push    word ptr namebuff
  149.         push    word ptr namebuff+2
  150.         xor     ax,ax
  151.         push    ax
  152.         call    sortproc            ; ディレクトリソート実行
  153. ;   @ifend
  154. @i0004:
  155. ;
  156.     mov     ax,2523h                ; Ctrl+C ベクタ復元
  157.     lds     dx,cs:orgint23h
  158.     int     21h
  159. ;
  160.     mov     ah,0dh              ; ディスクバッファ リセット
  161.     int     21h
  162. ;
  163.     mov     ax,4c00h                ; プログラム終了
  164.     int     21h
  165. ;
  166. main        endp
  167. ;
  168. ;------------------------------------------------------------------------------
  169. ;
  170. ;   sortproc
  171. ;       ディレクトリソートを実行する
  172. ;
  173. ;   TYPE    near call
  174. ;   IN      sp+2:ディレクトリ名リストアドレス
  175. ;           sp+6:ディレクトリ名バッファの空き領域の先頭
  176. ;           sp+8:ディレクトリ名バッファの空き領域サイズ
  177. ;   OUT     なし
  178. ;   保存レジスタ ds
  179. ;
  180. ;------------------------------------------------------------------------------
  181. ;
  182. sortproc    proc    near    curnameoff,curnameseg,freenameoff,freenamesiz
  183. ;
  184.     mov     di,curnameoff
  185.     mov     es,curnameseg
  186. ;   @do until
  187. @d0001:
  188.         mov     entrycount,0        ; 処理したエントリのカウンタを初期化
  189.         mov     sortcount,0
  190.         mov     movecount,0
  191.         mov     ah,0dh              ; ディスクバッファ リセット
  192.         int     21h
  193. ;
  194.         call    getdirinfo          ; ディレクトリ情報獲得
  195. ;       @if (zf,on),L
  196.           jz    @i0007
  197.           jmp   @i0008
  198. @i0007:
  199.             mov     di,curnameoff   ; ディレクトリ名表示
  200.             mov     es,curnameseg
  201.             call    dspdirname
  202.             call    readdirectory   ; ディレクトリ読み込み
  203. ;           @if (zf,on)
  204.               jnz   @i0009
  205. ;               @if (sortexec,=,YES),S
  206.                   cmp   sortexec,YES
  207.                   jne   @i0010
  208.                     call    selection   ; ソート対象エントリ取り出し
  209. ;                   @if (ax,>,1)
  210.                       cmp   ax,1
  211.                       jbe   @i0011
  212.                         push    ds
  213.                         mov     ax,ds
  214.                         mov     es,ax
  215.                         mov     ax,offset sortfuncs
  216.                         push    ax
  217.                         push    sortcount
  218.                         xor     ax,ax
  219.                         push    ax
  220.                         mov     ds,sortbuff
  221.                         call    dirqsort    ; クイックソート
  222.                         pop ds
  223. ;                   @ifend
  224. @i0011:
  225. ;                   @if (sweep,=,YES)
  226.                       cmp   sweep,YES
  227.                       jne   @i0012
  228.                         call    remainsweep ; ソート対象外エントリを掻き集める
  229. ;                   @ifend
  230. @i0012:
  231.                     call    copyback    ; ソートしたエントリを戻す
  232. ;               @else
  233.                   jmp short @i0013
  234. @i0010:
  235.                     call    predelete
  236.                     call    remainsweep
  237. ;               @ifend
  238. @i0013:
  239.                 call    filldeleted     ; 削除エントリの情報をクリアする
  240.                 mov     cs:critical,YES ; クリティカルセクション開始
  241.                 call    writedirectory  ; ディレクトリ書き込み
  242.                 call    dspmsgend       ; 終了メッセージ表示
  243.                 mov     cs:critical,NO  ; クリティカルセクション終了
  244. ;               @if (cs:breakflag,=,YES)    ; Ctrl+Cが押下されたので終了
  245.                   cmp   cs:breakflag,YES
  246.                   jne   @i0014
  247.                     mov     errorno,-1
  248.                     xor     cx,cx
  249.                     xor     dx,dx
  250.                     jmp     abort
  251. ;               @ifend
  252. @i0014:
  253. ;           @ifend
  254. @i0009:
  255. ;           @if (recursive,=,YES)   ; 再帰呼び出し
  256.               cmp   recursive,YES
  257.               jne   @i0015
  258.                 mov     ah,0dh      ; ディスクバッファ リセット
  259.                 int     21h
  260. ;
  261.                 mov     subsearch,YES   ;
  262.                 mov     di,curnameoff   ; サブディレクトリのリスト獲得
  263.                 mov     es,curnameseg
  264.                 call    strcopywild
  265.                 mov     word ptr srchname,di
  266.                 mov     word ptr srchname+2,es
  267.                 call    dirlist
  268.                 mov     ax,word ptr namebuff
  269. ;               @if (ax,/=,freenameoff) ; サブディレクトリ有りの時
  270.                   cmp   ax,freenameoff
  271.                   je    @i0016
  272.                     push    namebuffsiz
  273.                     push    ax
  274.                     push    word ptr namebuff+2
  275.                     push    freenameoff
  276.                     call    sortproc    ; ディレクトリソート再帰実行
  277. ;               @ifend
  278. @i0016:
  279.                 mov     si,freenameoff  ; 各ワーク情報を再帰実行から戻す
  280.                 mov     es,freenamesiz
  281.                 mov     namebuffsiz,es
  282.                 mov     word ptr namebuff,si
  283.                 mov     es,curnameseg
  284.                 mov     word ptr es:[si],0
  285.                 mov     subsearch,NO    ;
  286. ;           @ifend
  287. @i0015:
  288. ;       @ifend
  289. @i0008:
  290.         mov     di,curnameoff       ; 次の対象ディレクトリへ
  291.         mov     es,curnameseg
  292.         cld
  293.         xor     ax,ax
  294.         mov     cx,-1
  295.       repne scasb
  296.         mov     curnameoff,di
  297. ;   @doend (byte ptr es:[di],=,0),L ; ディレクトリリストの終了か?
  298.       cmp   byte ptr es:[di],0
  299.       je    @d0002
  300.       jmp   @d0001
  301. @d0002:
  302. ;
  303.     ret     8
  304. ;
  305. sortproc    endp
  306. ;
  307. ;------------------------------------------------------------------------------
  308. ;
  309. ;   getdirinfo
  310. ;       ディレクトリ及びその所属するドライブの情報を獲得する
  311. ;
  312. ;   TYPE    near call
  313. ;   IN      ds:di = ディレクトリ名
  314. ;   OUT     drvinf = DPBのコピー  その他 ディレクトリ情報
  315. ;   保存レジスタ bx,cx,dx,si,di,bp,ds,es
  316. ;
  317. ;------------------------------------------------------------------------------
  318. ;
  319. getdirinfo  proc    near
  320. ;
  321.     call    dirfind
  322. ;   @if (zf,on)
  323.       jnz   @i0017
  324.         mov     dirtype,ax          ; ディレクトリタイプ ルート/サブ
  325.         mov     subchain,ax         ; FATチェインの先頭
  326.         mov     driveno,dx          ; ドライブ番号
  327.         dec     driveno
  328. ;
  329.         mov     di,offset drvinf    ; Drive Parameter Block 取得
  330.         call    getdpb
  331. ;
  332. ;       @if (drvinf.datasector,<=,4086),S    ; 12bitFAT/16bitFAT
  333.           cmp   drvinf.datasector,4086
  334.           ja    @i0018
  335.             mov     fattype,FAT12            ;   v1.00バグ '='が無かった
  336. ;       @else
  337.           jmp short @i0019
  338. @i0018:
  339.             mov     fattype,FAT16
  340. ;       @ifend
  341. @i0019:
  342.         xor     ax,ax
  343.         mov     al,drvinf.sectorperalloc
  344.         inc     ax
  345.         mov     clustsect,ax        ; 1クラスタ当たりのセクタ数
  346.         mul     drvinf.sectorlength
  347.         mov     clustsize,ax        ; 1クラスタのバイトサイズ
  348.         xor     ax,ax
  349. ;   @ifend
  350. @i0017:
  351.     ret
  352. ;
  353. getdirinfo  endp
  354. ;
  355. ;------------------------------------------------------------------------------
  356. ;
  357. ;   getdpb
  358. ;       ドライブパラメータブロックをコピーする
  359. ;
  360. ;   TYPE    near call
  361. ;   IN      dl = ドライブ番号 A:1 B:2 ...
  362. ;           ds:di = drive parameter block をコピーする領域のアドレス
  363. ;   OUT     ax = 完了コード
  364. ;   保存レジスタ bx,cx,dx,si,di,bp,ds,es
  365. ;
  366. ;------------------------------------------------------------------------------
  367. ;
  368. getdpb      proc    near    uses bx cx si di ds es
  369. ;
  370.     cld
  371.     mov     ax,ds
  372.     mov     es,ax
  373.     mov     ah,32h                  ; DPBアドレス取得 非公開
  374.     mov     cx,10h
  375.     int     21h
  376. ;
  377.     mov     si,bx
  378.   rep   movsw                       ; DPB コピー
  379.     ret
  380. ;
  381. getdpb      endp
  382. ;
  383. ;------------------------------------------------------------------------------
  384. ;
  385. ;   readdirectory
  386. ;       ディレクトリを読み込む
  387. ;
  388. ;   TYPE    near call
  389. ;   IN      dirtype,driveno,drvinf構造体,fatdrive
  390. ;   OUT     ax = 完了コード     entrycount,clustcount
  391. ;   保存レジスタ bx,cx,dx,si,di,bp,ds,es
  392. ;
  393. ;------------------------------------------------------------------------------
  394. ;
  395. readdirectory   proc    near
  396. ;
  397. ;   @if (dirtype,=,0),S             ; ルートディレクトリ
  398.       cmp   dirtype,0
  399.       jne   @i0020
  400.         mov     ax,drvinf.directoryentry
  401. ;       @if (ax,<=,2048),S
  402.           cmp   ax,2048
  403.           ja    @i0021
  404.             mov     entrycount,ax   ; ディレクトリエントリ数 格納
  405.             mov     adjustroot,NO
  406.             call    readrootdir
  407. ;       @else
  408.           jmp short @i0022
  409. @i0021:
  410.             mov     entrycount,2048 ; ディレクトリエントリ数を2048とする
  411.             mov     adjustroot,YES  ; ルートのエントリ数評価を遅らせる
  412.             call    readrootdir
  413.             call    checkrootsize   ; エントリ数評価
  414. ;           @if (zf,off)
  415.               jz    @i0023
  416.                 mov     ah,9            ; ルートディレクトリサイズオーバー表示
  417.                 mov     dx,offset dirover
  418.                 int     21h
  419.                 mov     ax,-1
  420.                 jmp     rdirerror
  421. ;           @ifend
  422. @i0023:
  423. ;       @ifend
  424. @i0022:
  425. ;   @else
  426.       jmp short @i0024
  427. @i0020:
  428.         mov     ax,driveno          ; サブディレクトリ
  429. ;       @if (ax,/=,fatdrive)        ; 読み込み済FATと違うドライブ名の時
  430.           cmp   ax,fatdrive
  431.           je    @i0025
  432.             xor     ax,ax           ; FATサイズ計算
  433.             mov     al,drvinf.fatsector
  434.             mul     drvinf.sectorlength
  435. ;           @if (dx,=,1),and,(ax,=,0),or,(dx,=,0),S
  436.               cmp   dx,1
  437.               jne   @i0026
  438.               or    ax,ax
  439.               je    @i0027
  440. @i0026:
  441.               or    dx,dx
  442.               jne   @i0028
  443. @i0027:
  444.                 call    readfat     ; FAT読み込み
  445. ;           @else
  446.               jmp short @i0029
  447. @i0028:
  448.                 mov     ah,9        ; FATサイズオーバー表示
  449.                 mov     dx,offset fatover
  450.                 int     21h
  451.                 mov     ax,-1
  452.                 jmp     rdirerror
  453. ;           @ifend
  454. @i0029:
  455. ;       @ifend
  456. @i0025:
  457. ;
  458.         cld                         ; サブディレクトリのクラスタチェインを獲得
  459.         mov     di,offset subchain
  460.         mov     es,fatbuff
  461. ;       @if (fattype,=,FAT12),S
  462.           cmp   fattype,FAT12
  463.           jne   @i0030
  464.             call    getfat12chain
  465. ;       @else
  466.           jmp short @i0031
  467. @i0030:
  468.             call    getfat16chain
  469. ;       @ifend
  470. @i0031:
  471.         mov     clustcount,dx       ; サブディレクトリのクラスタ数を設定
  472.         mov     ax,dx
  473.         mul     clustsize
  474.         mov     cx,32               ; ディレクトリエントリ数 計算 格納
  475.         div     cx
  476. ;       @if (ax,<=,2048),S
  477.           cmp   ax,2048
  478.           ja    @i0032
  479.             mov     entrycount,ax
  480.             call    readsubdir      ; サブディレクトリ読み込み
  481. ;       @else
  482.           jmp short @i0033
  483. @i0032:
  484.             mov     ah,9            ; ディレクトリサイズオーバー表示
  485.             mov     dx,offset dirover
  486.             int     21h
  487.             mov     ax,-1
  488. ;       @ifend
  489. @i0033:
  490. ;   @ifend
  491. @i0024:
  492. rdirerror:
  493.     test    ax,ax
  494.     ret
  495. ;
  496. readdirectory   endp
  497. ;
  498. ;------------------------------------------------------------------------------
  499. ;
  500. ;   readrootdir
  501. ;       ルートディレクトリの内容をメモリに読み込む
  502. ;
  503. ;   TYPE    near call
  504. ;   IN      drive parameter block 領域      adjustroot
  505. ;   OUT     dirbuff = 読み込んだディレクトリのセグメントアドレス
  506. ;   保存レジスタ bp,ds,es
  507. ;
  508. ;------------------------------------------------------------------------------
  509. ;
  510. readrootdir     proc    near    uses bp
  511. ;
  512. ;   @if (adjustroot,=,NO),S
  513.       cmp   adjustroot,NO
  514.       jne   @i0034
  515.         mov     ax,drvinf.datastartsector ; ディレクトリサイズ計算とメモリ獲得
  516.         sub     ax,drvinf.directorystart
  517. ;   @else
  518.       jmp short @i0035
  519. @i0034:
  520.         xor     ax,ax                     ; ルートディレクトリが2048を超えて
  521.         mov     dx,1                      ; いる場合の暫定措置
  522.         div     drvinf.sectorlength
  523. ;   @ifend
  524. @i0035:
  525.     mov     sectcount,ax
  526.     mul     drvinf.sectorlength
  527.     mov     dirsize,ax
  528.     call    dosallocx
  529.     mov     dirbuff,ax
  530. ;
  531.     push    ds                      ; ルートディレクトリ読み込み
  532.     mov     ax,driveno
  533.     xor     bx,bx
  534.     mov     cx,sectcount
  535.     mov     dx,drvinf.directorystart
  536.     mov     ds,dirbuff
  537.     int     25h
  538. ;   @if (cf,on)
  539.       jnc   @i0036
  540.         xor     cx,cx
  541.         xor     dx,dx
  542.         jmp     abort
  543. ;   @ifend
  544. @i0036:
  545.     popf
  546.     pop     ds
  547.     xor     ax,ax
  548.     ret
  549. ;
  550. readrootdir     endp
  551. ;
  552. ;------------------------------------------------------------------------------
  553. ;
  554. ;   checkrootsize
  555. ;       ルートディレクトリのエントリ数をチェックする
  556. ;
  557. ;   TYPE    near call
  558. ;   IN      dirbuff = 読み込んだディレクトリのセグメントアドレス
  559. ;   OUT     ax = 0 ディレクトリ数が範囲内    ax /= 0 範囲オーバー
  560. ;   保存レジスタ bx,cx,dx,si,di,bp,ds,es
  561. ;
  562. ;------------------------------------------------------------------------------
  563. ;
  564. checkrootsize   proc    near    uses di es
  565. ;
  566.     xor     di,di                   ; オフセットを0
  567.     mov     es,dirbuff              ; ディレクトリバッファセグメントを取得
  568. ;   @do until
  569. @d0003:
  570. ;       @if (byte ptr es:[di],=,0)  ; 最終エントリを発見したかの判定
  571.           cmp   byte ptr es:[di],0
  572.           jne   @i0037
  573.             xor     ax,ax           ; 有効+削除エントリが64KB未満(範囲内)
  574.             jmp     chrtszfind
  575. ;       @ifend
  576. @i0037:
  577.         lea     di,[di+direntrysize] ; 次のエントリへ
  578. ;   @doend (di,=,0)                 ; 64KBひとまわりしたか?
  579.       or    di,di
  580.       jne   @d0003
  581.     mov     ax,-1                   ; 扱える範囲を超えている
  582. chrtszfind:
  583.     test    ax,ax
  584.     ret
  585. ;
  586. checkrootsize   endp
  587. ;
  588. ;------------------------------------------------------------------------------
  589. ;
  590. ;   readfat
  591. ;       FATを読み込むための領域を獲得し、FATを読み込む
  592. ;
  593. ;   TYPE    near call
  594. ;   IN      drive parameter block 領域
  595. ;   OUT     fatbuff = 読み込んだFATのセグメントアドレス
  596. ;   保存レジスタ bp,ds,es
  597. ;
  598. ;------------------------------------------------------------------------------
  599. ;
  600. readfat     proc    near    uses bp
  601. ;
  602. ;   @if (fatdrive,/=,-1)            ; 既に別のFATを読み込み済の時、解放する
  603.       cmp   fatdrive,-1
  604.       je    @i0038
  605.         mov     es,fatbuff
  606.         int     21h
  607.         mov     fatdrive,-1
  608.         mov     fatbuff,0
  609. ;   @ifend
  610. @i0038:
  611.     xor     ax,ax                   ; FAT用領域獲得
  612.     mov     al,drvinf.fatsector
  613.     mul     drvinf.sectorlength
  614.     call    dosallocx
  615.     mov     fatbuff,ax
  616. ;
  617.     push    ds                      ; FAT読み込み
  618.     mov     ax,driveno
  619.     mov     fatdrive,ax
  620.     xor     bx,bx
  621.     xor     cx,cx
  622.     mov     cl,drvinf.fatsector
  623.     mov     dx,drvinf.reservedsector
  624.     mov     ds,fatbuff
  625.     int     25h
  626. ;   @if (cf,on)
  627.       jnc   @i0039
  628.         xor     cx,cx
  629.         xor     dx,dx
  630.         jmp     abort
  631. ;   @ifend
  632. @i0039:
  633.     popf
  634.     pop     ds
  635.     ret
  636. ;
  637. readfat     endp
  638. ;
  639. ;------------------------------------------------------------------------------
  640. ;
  641. ;   getfat12chain
  642. ;       12ビットFATのチェインをたどって、配列に書き出す。
  643. ;
  644. ;   TYPE    near call
  645. ;   IN      es:オフセット0= FAT領域
  646. ;           ds:di = FATチェインを書き出す配列、 及びその先頭に最初のクラスタ
  647. ;           番号を格納しておくこと
  648. ;   OUT     dx = チェインの総クラスタ数
  649. ;   保存レジスタ si,bp,ds,es
  650. ;
  651. ;------------------------------------------------------------------------------
  652. ;
  653. getfat12chain   proc    near
  654. ;
  655.     mov     cl,4
  656.     xor     dx,dx
  657. ;   @do while,(word ptr [di],<,FAT12)
  658. @d0004:
  659.       cmp   word ptr [di],FAT12
  660.       jae   @d0005
  661.         mov     bx,[di]
  662.         mov     ax,bx
  663.         shr     ax,1
  664.         add     bx,ax
  665.         mov     ax,es:[bx]
  666. ;       @if (word ptr [di],off,1),S
  667.           test  word ptr [di],1
  668.           jnz   @i0040
  669.             and     ax,0fffh
  670. ;       @else
  671.           jmp short @i0041
  672. @i0040:
  673.             shr     ax,cl
  674. ;       @ifend
  675. @i0041:
  676.         lea     di,[di+2]
  677.         mov     [di],ax
  678.         inc     dx
  679. ;   @doend
  680.       jmp   @d0004
  681. @d0005:
  682.     ret
  683. ;
  684. getfat12chain   endp
  685. ;
  686. ;------------------------------------------------------------------------------
  687. ;
  688. ;   getfat16chain
  689. ;       16ビットFATのチェインをたどって、配列に書き出す。
  690. ;
  691. ;   TYPE    near call
  692. ;   IN      es:オフセット0 = FAT領域
  693. ;           ds:di = FATチェインを書き出す配列、 及びその先頭に最初のクラスタ
  694. ;           番号を格納しておくこと
  695. ;   OUT     dx = チェインの総クラスタ数
  696. ;   保存レジスタ cx,si,bp,ds,es
  697. ;
  698. ;------------------------------------------------------------------------------
  699. ;
  700. getfat16chain   proc    near
  701. ;
  702.     xor     dx,dx
  703. ;   @do while,(word ptr [di],<,FAT16)
  704. @d0006:
  705.       cmp   word ptr [di],FAT16
  706.       jae   @d0007
  707.         mov     bx,[di]
  708.         shl     bx,1
  709.         mov     ax,es:[bx]
  710.         lea     di,[di+2]
  711.         mov     [di],ax
  712.         inc     dx
  713. ;   @doend
  714.       jmp   @d0006
  715. @d0007:
  716.     ret
  717. ;
  718. getfat16chain   endp
  719. ;
  720. ;------------------------------------------------------------------------------
  721. ;
  722. ;   readsubdir
  723. ;       サブディレクトリを読み込む
  724. ;
  725. ;   TYPE    near call
  726. ;   IN      clustcount ディレクトリのクラスタ数
  727. ;   OUT     dirbuff = 読み込んだディレクトリのセグメントアドレス
  728. ;   保存レジスタ cx,si,bp,ds,es
  729. ;
  730. ;------------------------------------------------------------------------------
  731. ;
  732. readsubdir  proc    near
  733.     local cluster:word
  734. ;
  735.     mov     dx,clustcount           ; ディレクトリサイズ計算
  736.     mov     cluster,dx
  737.     mov     ax,clustsect
  738.     mul     dx
  739.     mul     drvinf.sectorlength
  740.     mov     dirsize,ax
  741.     call    dosallocx               ; ディレクトリバッファ獲得
  742.     mov     dirbuff,ax
  743.     xor     bx,bx
  744.     mov     di,offset subchain      ; ディレクトリクラスタチェインの先頭
  745. ;
  746.     push    ds
  747.     mov     ax,ds
  748.     mov     es,ax
  749.     mov     ds,dirbuff
  750. ;   @do until
  751. @d0008:
  752.         mov     ax,es:[di]          ; ディレクトリクラスタ読み込み
  753.         sub     ax,2
  754.         mov     cx,es:clustsect
  755.         mul     cx
  756.         add     ax,es:drvinf.datastartsector
  757.         mov     dx,ax
  758.         mov     ax,es:driveno
  759.         push    bp
  760.         push    di
  761.         int     25h
  762. ;       @if (cf,on)
  763.           jnc   @i0042
  764.             xor     cx,cx
  765.             xor     dx,dx
  766.             jmp     abort
  767. ;       @ifend
  768. @i0042:
  769.         popf
  770.         pop     di
  771.         pop     bp
  772.         add     bx,es:clustsize     ; 次のバッファオフセット
  773.         lea     di,[di+2]           ; 次のクラスタ
  774.         dec     cluster             ; カウントダウン
  775. ;   @doend (zf,on)
  776.       jnz   @d0008
  777.     pop ds
  778.     xor     ax,ax
  779.     ret
  780. ;
  781. readsubdir  endp
  782. ;
  783. ;------------------------------------------------------------------------------
  784. ;
  785. ;   selection
  786. ;       読み込んだディレクトリからattributeで指定されたエントリを選択して
  787. ;       ソートバッファに移動する
  788. ;
  789. ;   TYPE    near call
  790. ;   IN      dirbuff = 読み込んだディレクトリのセグメントアドレス その他
  791. ;   OUT     sortbuff = ソート対象を選択・移動したセグメントアドレス
  792. ;   保存レジスタ bp,ds
  793. ;
  794. ;------------------------------------------------------------------------------
  795. ;
  796. selection   proc    near
  797. ;
  798.     mov     ax,dirsize              ; ディレクトリサイズからバッファサイズ
  799. ;   @if (ax,/=,0),S                 ; 64KB未満
  800.       or    ax,ax
  801.       je    @i0043
  802.         xor     dx,dx
  803. ;   @else                           ; 64KB
  804.       jmp short @i0044
  805. @i0043:
  806.         mov     dx,1
  807. ;   @ifend
  808. @i0044:
  809.     call    dosallocx               ; ソートバッファ獲得
  810.     mov     sortbuff,ax
  811.     mov     es,ax
  812.     mov     bx,attribute            ; 選出属性
  813.     mov     dx,entrycount           ; エントリ数
  814.     xor     si,si
  815.     xor     di,di
  816. ;   @if (dirtype,/=,0)              ; サブディレクトリの時は最初の2つを除外
  817.       cmp   dirtype,0
  818.       je    @i0045
  819.         sub     dx,2
  820.         mov     si,64
  821. ;   @ifend
  822. @i0045:
  823. ;
  824.     push    ds
  825.     cld
  826.     xor     ax,ax
  827.     mov     ds,dirbuff
  828. ;   @do while,(dx,/=,0),and,(byte ptr [si],/=,0)
  829. @d0009:
  830.       or    dx,dx
  831.       je    @d0010
  832.       cmp   byte ptr [si],0
  833.       je    @d0010
  834. ;       @cbegin
  835. ;       @case (byte ptr [si],=,0e5h),S  ; 削除エントリか?
  836.           cmp   byte ptr [si],0e5h
  837.           jne   @c0002
  838.             mov     byte ptr [si],0     ; 後の処理のために0を書いておく
  839.             lea     si,[si+20h]
  840. ;       @case (byte ptr [si+0bh],on,bl),S   ; 属性違いか?
  841.           jmp short @c0001
  842. @c0002:
  843.           test  byte ptr [si+0bh],bl
  844.           jz    @c0003
  845.             lea     si,[si+20h]
  846. ;       @other                      ; ソートバッファへ移動
  847.           jmp short @c0001
  848. @c0003:
  849.             mov     cx,10h
  850.           rep   movsw
  851.             mov     byte ptr [si-20h],0 ; 移動元に0を書いておく
  852. ;           @if (byte ptr [di-20h],=,5) ; 名前の頭がE5用のコードなら戻しておく
  853.               cmp   byte ptr [di-20h],5
  854.               jne   @i0046
  855.                 mov     byte ptr [di-20h],0e5h
  856. ;           @ifend
  857. @i0046:
  858.             inc     ax              ; 移動したエントリ数を加算
  859. ;       @cend
  860. @c0001:
  861.         dec     dx                  ; カウントダウン
  862. ;   @doend
  863.       jmp   @d0009
  864. @d0010:
  865.     pop     ds
  866.     mov     sortcount,ax            ; 移動したエントリ数を記録
  867.     ret
  868. ;
  869. selection   endp
  870. ;
  871. ;------------------------------------------------------------------------------
  872. ;
  873. ;   predelete
  874. ;       後のremainsweepルーチンのために削除エントリの先頭を00とする
  875. ;
  876. ;   TYPE    near call
  877. ;   IN      entrycount,dirbuff
  878. ;   OUT     なし
  879. ;   保存レジスタ ax,bx,dx,si,bp,ds
  880. ;
  881. ;------------------------------------------------------------------------------
  882. ;
  883. predelete   proc    near
  884. ;
  885.     mov     cx,entrycount
  886.     xor     di,di
  887.     mov     es,dirbuff
  888. ;   @do until
  889. @d0011:
  890. ;       @if (byte ptr es:[di],=,0e5h)
  891.           cmp   byte ptr es:[di],0e5h
  892.           jne   @i0047
  893.             mov     byte ptr es:[di],0
  894. ;       @ifend
  895. @i0047:
  896.         lea     di,[di+20h]
  897.         dec     cx
  898. ;   @doend (zf,on)
  899.       jnz   @d0011
  900.     ret
  901. ;
  902. predelete   endp
  903. ;
  904. ;------------------------------------------------------------------------------
  905. ;
  906. ;   remainsweep
  907. ;       ソート対象外のエントリをディレクトリバッファの先頭に集める
  908. ;
  909. ;   TYPE    near call
  910. ;   IN      entrycount,dirbuff
  911. ;   OUT     movecount
  912. ;   保存レジスタ ax,bp,ds
  913. ;
  914. ;------------------------------------------------------------------------------
  915. ;
  916. remainsweep proc    near
  917. ;
  918.     cld
  919.     push    ds
  920.     xor     bx,bx
  921.     mov     dx,entrycount           ; ディレクトリのエントリサイズ
  922.     mov     es,dirbuff
  923.     mov     ds,dirbuff
  924.     xor     di,di
  925. ;   @do while,(byte ptr [di],/=,0),and,(dx,/=,0) ; 最初の空きエントリ位置取得
  926. @d0012:
  927.       cmp   byte ptr [di],0
  928.       je    @d0013
  929.       or    dx,dx
  930.       je    @d0013
  931.         lea     di,[di+20h]
  932.         dec     dx
  933. ;   @doend
  934.       jmp   @d0012
  935. @d0013:
  936.     mov     si,di
  937. ;   @do until
  938. @d0014:
  939. ;       @do while,(byte ptr [si],=,0),and,(dx,/=,0) ; 次の有効エントリ位置取得
  940. @d0015:
  941.           cmp   byte ptr [si],0
  942.           jne   @d0016
  943.           or    dx,dx
  944.           je    @d0016
  945.             lea     si,[si+20h]
  946.             dec     dx
  947. ;       @doend
  948.           jmp   @d0015
  949. @d0016:
  950. ;       @if (dx,/=,0)               ; 終了でなければエントリを頭へ詰める
  951.           or    dx,dx
  952.           je    @i0048
  953.             inc     bx
  954.             mov     cx,10h
  955.           rep   movsw
  956.             mov     byte ptr [si-20h],0 ; 移動元を空きエントリとする
  957.             dec     dx              ; カウントダウン
  958. ;           @do while,(byte ptr [di],/=,0)  ; 次の空きエントリ位置取得
  959. @d0017:
  960.               cmp   byte ptr [di],0
  961.               je    @d0018
  962.                 lea     di,[di+20h]
  963. ;           @doend
  964.               jmp   @d0017
  965. @d0018:
  966. ;       @ifend
  967. @i0048:
  968. ;   @doend (dx,=,0)
  969.       or    dx,dx
  970.       jne   @d0014
  971.     pop     ds
  972.     mov     movecount,bx            ; 移動したエントリ数を記録
  973.     ret
  974. ;
  975. remainsweep endp
  976. ;
  977. ;------------------------------------------------------------------------------
  978. ;
  979. ;   copyback
  980. ;       ソートバッファの内容をディレクトリバッファへ書き戻す
  981. ;
  982. ;   TYPE    near call
  983. ;   IN      sortcount,sortbuff,dirbuff
  984. ;   OUT     dirbuff
  985. ;   保存レジスタ    bx,bp,ds
  986. ;
  987. ;------------------------------------------------------------------------------
  988. ;
  989. copyback    proc    near    uses ds
  990. ;
  991.     cld
  992.     mov     dx,sortcount            ; ソートバッファ上のエントリ数
  993.     mov     es,dirbuff
  994.     mov     ds,sortbuff
  995.     xor     si,si
  996.     xor     di,di
  997. ;   @do while,(dx,/=,0)
  998. @d0019:
  999.       or    dx,dx
  1000.       je    @d0020
  1001. ;       @if (byte ptr es:[di],=,0),S    ; ディレクトリバッファは空きエントリ?
  1002.           cmp   byte ptr es:[di],0
  1003.           jne   @i0049
  1004. ;           @if (byte ptr [si],=,0e5h)  ; 名前の頭がE5なら、変換しておく
  1005.               cmp   byte ptr [si],0e5h
  1006.               jne   @i0050
  1007.                 mov     byte ptr [si],05h
  1008. ;           @ifend
  1009. @i0050:
  1010.             mov     cx,10h          ; コピー
  1011.           rep   movsw
  1012.             dec     dx              ; カウントダウン
  1013. ;       @else
  1014.           jmp short @i0051
  1015. @i0049:
  1016.             lea di,[di+20h]         ; 次のディレクトリバッファエントリへ
  1017. ;       @ifend
  1018. @i0051:
  1019. ;   @doend
  1020.       jmp   @d0019
  1021. @d0020:
  1022. ;
  1023.     mov     ax,ds                   ; ソートバッファの解放
  1024.     mov     es,ax
  1025.     mov     ah,49h
  1026.     int     21h
  1027. ;
  1028.     ret
  1029. ;
  1030. copyback    endp
  1031. ;
  1032. ;------------------------------------------------------------------------------
  1033. ;
  1034. ;   filldeleted
  1035. ;       ディレクトリ中の削除エントリをクリアする
  1036. ;
  1037. ;   TYPE    near call
  1038. ;   IN      dirsize,dirbuff
  1039. ;   OUT     なし
  1040. ;   保存レジスタ    bx,dx,bp,ds
  1041. ;
  1042. ;------------------------------------------------------------------------------
  1043. ;
  1044. filldeleted proc    near
  1045. ;
  1046.     cld
  1047.     mov     ax,0f6h                 ; 埋め込みデータの設定 
  1048.     mov     si,dirsize              ; ディレクトリの最終ポイント取得
  1049.     mov     es,dirbuff
  1050. ;   @do until
  1051. @d0021:
  1052.         lea     si,[si-20h]         ; 最終位置から先頭方向へ
  1053. ;       @if (byte ptr es:[si],=,0),S    ; 削除エントリ判定
  1054.           cmp   byte ptr es:[si],0
  1055.           jne   @i0052
  1056.             mov     es:[si],ah      ; 頭1バイト 0orE5
  1057.             mov     cx,1fh          ; 残り31バイトをF6で埋める
  1058.             lea     di,[si+1]
  1059.           rep   stosb
  1060. ;       @else                       ; 有効エントリが見つかったので
  1061.           jmp short @i0053
  1062. @i0052:
  1063.             mov     ah,0e5h         ; それ以後は頭1バイトをE5に変更
  1064. ;       @ifend
  1065. @i0053:
  1066. ;   @doend (si,=,0)                 ; ディレクトリ先頭になるまで
  1067.       or    si,si
  1068.       jne   @d0021
  1069.     ret
  1070. ;
  1071. filldeleted endp
  1072. ;
  1073. ;------------------------------------------------------------------------------
  1074. ;
  1075. ;   writedirectory
  1076. ;       ディレクトリバッファをファイルに書き戻す
  1077. ;
  1078. ;   TYPE    near call
  1079. ;   IN      dirtype,driveno,drvinf構造体,sectcount,clustcount,dirbuff
  1080. ;           clustsect,clustsize,subchain
  1081. ;   OUT     なし
  1082. ;   保存レジスタ
  1083. ;
  1084. ;------------------------------------------------------------------------------
  1085. ;
  1086. writedirectory  proc    near
  1087.         local cluster:word
  1088. ;
  1089. ;   @if (dirtype,=,0),S
  1090.       cmp   dirtype,0
  1091.       jne   @i0054
  1092.         push    ds                  ; ルートディレクトリ書き込み
  1093.         mov     ax,driveno
  1094.         xor     bx,bx
  1095.         mov     cx,sectcount
  1096.         mov     dx,drvinf.directorystart
  1097.         mov     ds,dirbuff
  1098.         push    bp
  1099.         int     26h
  1100. ;       @if (cf,on)
  1101.           jnc   @i0055
  1102.             xor     cx,cx
  1103.             xor     dx,dx
  1104.             jmp     abort
  1105. ;       @ifend
  1106. @i0055:
  1107.         popf
  1108.         pop     bp
  1109.         pop     ds
  1110. ;   @else
  1111.       jmp short @i0056
  1112. @i0054:
  1113.         push    ds                  ; サブディレクトリ書き込み
  1114.         mov     ax,clustcount
  1115.         mov     cluster,ax
  1116.         mov     di,offset subchain
  1117.         mov     ax,ds
  1118.         mov     es,ax
  1119.         xor     bx,bx
  1120.         mov     ds,dirbuff
  1121. ;       @do until
  1122. @d0022:
  1123.             mov     ax,es:[di]
  1124.             sub     ax,2
  1125.             mov     cx,es:clustsect
  1126.             mul     cx
  1127.             add     ax,es:drvinf.datastartsector
  1128.             mov     dx,ax
  1129.             mov     ax,es:driveno
  1130.             push    bp
  1131.             push    di
  1132.             int     26h
  1133. ;           @if (cf,on)
  1134.               jnc   @i0057
  1135.                 xor     cx,cx
  1136.                 xor     dx,dx
  1137.                 jmp abort
  1138. ;           @ifend
  1139. @i0057:
  1140.             popf
  1141.             pop     di
  1142.             pop     bp
  1143.             add     bx,es:clustsize
  1144.             lea     di,[di+2]
  1145.             dec     cluster
  1146. ;       @doend (zf,on)
  1147.           jnz   @d0022
  1148.         pop     ds
  1149. ;   @ifend
  1150. @i0056:
  1151. ;
  1152.     mov     es,dirbuff              ; ソートバッファの開放
  1153.     mov     ah,49h
  1154.     int     21h
  1155. ;
  1156.     ret
  1157. ;
  1158. writedirectory  endp
  1159. ;
  1160. ;------------------------------------------------------------------------------
  1161. ;
  1162. ;   dspdirname
  1163. ;       処理中ディレクトリ名を表示する
  1164. ;
  1165. ;   TYPE    near call
  1166. ;   IN      ES:DI ディレクトリ名文字列アドレス
  1167. ;   OUT     なし
  1168. ;   保存レジスタ    DS
  1169. ;
  1170. ;------------------------------------------------------------------------------
  1171. ;
  1172. dspdirname  proc
  1173. ;
  1174.     mov     ah,9        ; 処理中メッセージ表示
  1175.     mov     dx,offset procs
  1176.     int     21h
  1177. ;
  1178.     cld                             ; ディレクトリ名長さを獲得
  1179.     mov     cx,-1
  1180.     xor     ax,ax
  1181.     mov     dx,di
  1182.   repne     scasb
  1183.     not     cx
  1184.     dec     cx
  1185. ;
  1186.     push    ds                      ; ディレクトリ名表示
  1187.     mov     ax,es
  1188.     mov     ds,ax
  1189.     call    dosstdout
  1190.     pop     ds
  1191. ;
  1192.     mov     ah,2                ; 行頭への復帰
  1193.     mov     dl,0dh
  1194.     int     21h
  1195. ;
  1196.     ret
  1197. ;
  1198. dspdirname  endp
  1199. ;
  1200. ;------------------------------------------------------------------------------
  1201. ;
  1202. ;   dspmsgend
  1203. ;       処理終了メッセージを表示する
  1204. ;
  1205. ;   TYPE    near call
  1206. ;   IN      sortcount,movecount,sortproc,sweep
  1207. ;   OUT     なし
  1208. ;   保存レジスタ    ax,bx,cx,dx,si,di,bp,ds,es
  1209. ;
  1210. ;------------------------------------------------------------------------------
  1211. ;
  1212. dspmsgend   proc    uses ax bx cx dx si di ds es
  1213.         local   wrks:dword,wrka:word
  1214. ;
  1215.     mov     ax,sortcount            ; ソートしたエントリ数
  1216.     mov     bx,movecount            ; 移動したエントリ数
  1217.     mov     cx,ax
  1218.     add     cx,bx
  1219. ;   @cbegin
  1220. ;   @case (sortexec,=,YES),and,(sweep,=,YES),and,(cx,/=,0),S ; ソート&移動
  1221.       cmp   sortexec,YES
  1222.       jne   @c0005
  1223.       cmp   sweep,YES
  1224.       jne   @c0005
  1225.       or    cx,cx
  1226.       je    @c0005
  1227.         mov     ax,cx
  1228.         mov     si,offset bothmsg
  1229. ;   @case (sortexec,=,YES),and,(sweep,=,NO),and,(ax,/=,0),S ; ソートのみ
  1230.       jmp short @c0004
  1231. @c0005:
  1232.       cmp   sortexec,YES
  1233.       jne   @c0006
  1234.       cmp   sweep,NO
  1235.       jne   @c0006
  1236.       or    ax,ax
  1237.       je    @c0006
  1238. ;       @if (ax,>,1),S
  1239.           cmp   ax,1
  1240.           jbe   @i0058
  1241.             mov     si,offset sortmsg   ; 2つ以上ならソートのみ表示
  1242. ;       @else
  1243.           jmp short @i0059
  1244. @i0058:
  1245.             mov     si,offset bothmsg   ; 1つだけならソート&移動表示
  1246. ;       @ifend
  1247. @i0059:
  1248. ;   @case (sortexec,=,NO),and,(sweep,=,YES),and,(bx,/=,0),S ; 移動のみ
  1249.       jmp short @c0004
  1250. @c0006:
  1251.       cmp   sortexec,NO
  1252.       jne   @c0007
  1253.       cmp   sweep,YES
  1254.       jne   @c0007
  1255.       or    bx,bx
  1256.       je    @c0007
  1257.         mov     ax,cx
  1258.         mov     si,offset movemsg   ; 移動
  1259. ;   @other
  1260.       jmp short @c0004
  1261. @c0007:
  1262.         xor     ax,ax
  1263.         mov     si,offset nothmsg   ; 対象なし
  1264. ;   @cend
  1265. @c0004:
  1266. ;   @if (ax,/=,0)
  1267.       or    ax,ax
  1268.       je    @i0060
  1269.         mov     di,ss               ; 処理したエントリ数表示
  1270.         mov     es,di
  1271.         lea     di,offset wrka+1
  1272.         call    inttoasc0
  1273.         lea     di,[di-5]           ; 0サプレス処理
  1274.         push    di
  1275.         mov     cx,4
  1276. ;       @do while,(byte ptr es:[di],=,'0'),and,(cx,/=,0)
  1277. @d0023:
  1278.           cmp   byte ptr es:[di],'0'
  1279.           jne   @d0024
  1280.           or    cx,cx
  1281.           je    @d0024
  1282.             mov     byte ptr es:[di],' '
  1283.             inc     di
  1284.             dec     cx
  1285. ;       @doend
  1286.           jmp   @d0023
  1287. @d0024:
  1288.         mov     cx,5                ; エントリ数表示
  1289.         pop     dx
  1290.         mov     di,ds
  1291.         push    ss
  1292.         pop     ds
  1293.         call    dosstdout
  1294.         mov     ds,di
  1295. ;   @ifend
  1296. @i0060:
  1297.     mov     ah,9                    ; エントリ数に続くメッセージ表示
  1298.     mov     dx,si
  1299.     int     21h
  1300.     ret
  1301. ;
  1302. dspmsgend   endp
  1303. ;
  1304. ;------------------------------------------------------------------------------
  1305. ;
  1306. ;   altint23h
  1307. ;       Ctrl+C押下の横取り
  1308. ;
  1309. ;   TYPE    interrupt
  1310. ;   IN      なし
  1311. ;   OUT     なし
  1312. ;   保存レジスタ    ax,bx,cx,dx,si,di,bp,ds,es
  1313. ;
  1314. ;------------------------------------------------------------------------------
  1315. ;
  1316. altint23h   proc
  1317. ;
  1318. ;   @if (cs:critical,=,NO),S        ; クリティカルセクションではない時
  1319.       cmp   cs:critical,NO
  1320.       jne   @i0061
  1321.         jmp     cs:orgint23h        ; 既存の終了処理へ
  1322. ;   @else                           ; クリティカルセクションの時
  1323.       jmp short @i0062
  1324. @i0061:
  1325.         mov     cs:breakflag,YES    ; Ctrl+C押下を記憶しただけで復帰
  1326.         iret
  1327. ;   @ifend
  1328. @i0062:
  1329. ;
  1330. altint23h   endp
  1331. ;
  1332.         end     main
  1333.