home *** CD-ROM | disk | FTP | other *** search
/ Phoenix CD 2.0 / Phoenix_CD.cdr / 11a / chain.zip / CHAIN.ASM next >
Assembly Source File  |  1986-08-22  |  23KB  |  564 lines

  1. PAGE ,132
  2. TITLE IBM-PC File Chain Program, Version 2.14, 21-Aug-1986
  3.  
  4. ;
  5. ; Written By Steven Georgiades
  6. ;
  7. ; IBM-PC/XT File Chain Program
  8. ;   Will respond with a list of the disk clusters that make up the file chain
  9. ;   for the requested file.
  10. ;
  11. ;       If you are using this program and find it of value, your
  12. ;       contribution in any amount ($5.00 suggested) will be greatly
  13. ;       appreciated.  Makes checks payable to Steven M. Georgiades.
  14. ;               Thank you.
  15. ;
  16. ;       If you have any questions or comments about this or any other
  17. ;       SMG program, call or write:
  18. ;
  19. ;               Steven M. Georgiades
  20. ;               701-H South Hayward Street
  21. ;               Anaheim, CA 92804
  22. ;               (714) 826-9549
  23. ;
  24.  
  25. CODE      SEGMENT BYTE PUBLIC 'CODE'
  26.  
  27.           ASSUME  CS:CODE,DS:CODE,ES:CODE,SS:CODE
  28.  
  29.           ORG     5CH
  30.  
  31. FCB       LABEL   BYTE
  32.  
  33.           ORG     80H
  34.  
  35. PARAM     LABEL   BYTE
  36.  
  37.           ORG     100H
  38.  
  39. CHAIN:    JMP     BEGIN
  40.  
  41. ANDSTR    DB      " , $"
  42. CHAINMSG1 DB      "The Chain for $"
  43. CHAINMSG2 DB      " is:",13,10,10,"$"
  44. CHAINMSG3 DB      13,10,10
  45. CHAINMSG4 DB      "Total Clusters in File =  XXXXX",13,10,10
  46. CHAINMSG5 DB      "Physical File Length = XXXXXXXX",13,10
  47. CHAINMSG6 DB      "Logical  File Length = XXXXXXXX ("
  48. PERCENT   DB      " 0.00% Waste)",13,10,"$"
  49. CLSTSTR   DB      "XXXXX$"
  50. PRCNT100  DB      "100.0"
  51. SIGNON    DB      "Chain, Version 2.14",13,10,10,"$"
  52. SPECERR   DB      "Invalid File or Path Specification",7,": $"
  53. THRUSTR   DB      " to$"
  54. CRLF      DB      13,10,"$"
  55.  
  56. CLSTSEC   DW      ?
  57. DIR_LEN   DW      ?
  58. DIRBUF    DW      ?
  59. DIRSEC    DW      ?
  60. DRIVE     DB      ?
  61. EOF       DW      0FF8H
  62. FATSEC    DW      ?
  63. FATSIZE   DB      3
  64. FILENAME  DB      13 DUP(0)
  65. PREV      DW      ?
  66. RANGE     DB      0
  67. SECSIZE   DW      ?
  68. SIZLSB    DW      ?
  69. SIZMSB    DW      ?
  70. STARTSEC  DW      ?
  71.  
  72. FILESPEC  DB      "$",79 DUP(0)
  73.  
  74. BEGIN:    MOV     AH,9                          ; Output Sign-On Message
  75.           MOV     DX,OFFSET SIGNON
  76.           INT     21H
  77.           MOV     AH,19H                        ; Get Default Drive
  78.           INT     21H
  79.           MOV     DRIVE,AL                      ;   and Save
  80.           MOV     SI,OFFSET PARAM               ; Set up Pointer to Parameter
  81.           LODSB                                 ; Read Parameter Length
  82.           CBW
  83.           MOV     BX,AX
  84.           MOV     BYTE PTR [SI][BX],0           ; Terminate Parameter String
  85. STRIP:    LODSB                                 ; Strip Off Leading Whitespace
  86.           CMP     AL,' '
  87.           JE      STRIP
  88.           CMP     AL,9
  89.           JE      STRIP
  90.           OR      AL,AL                         ; If End-of-Parameter, Error
  91.           JNZ     NO_ERR1
  92.           JMP     ERROR
  93. NO_ERR1:  DEC     SI                            ; ReUse Last Character
  94.           MOV     DI,OFFSET FILESPEC            ; Point to FileSpec Buffer
  95.           CMP     BYTE PTR [SI+1],':'           ; If 2nd Character is Colon,
  96.           JNE     GET_PATH
  97.           SUB     AL,'A'                        ;   Get Drive Number
  98.           MOV     DRIVE,AL
  99.           ADD     SI,2                          ;   and Scan Past
  100. GET_PATH: MOV     AL,DRIVE                      ; Get Drive Number
  101.           ADD     AL,'A'                        ; Convert to Drive Number 
  102.           STOSB                                 ;   in FileSpec
  103.           MOV     AL,':'                        ; Add Colon to FileSpec
  104.           STOSB
  105.           CMP     BYTE PTR [SI],'\'             ; If Next Character is not '\',
  106.           JE      COPYPATH
  107.           MOV     AL,'\'
  108.           STOSB
  109.           PUSH    SI                            ;   Get Current Path to FileSpec
  110.           MOV     SI,DI
  111.           MOV     AH,47H
  112.           MOV     DL,DRIVE
  113.           INC     DL
  114.           INT     21H
  115.           POP     SI
  116.           MOV     AL,0                          ;   Find End-of-FileSpec
  117.           MOV     CX,64
  118.           REPNE   SCASB
  119.           JE      NO_ERR2
  120.           JMP     ERROR
  121. NO_ERR2:  DEC     DI
  122.           CMP     BYTE PTR [DI-1],'\'           ;   If Root DIR, Skip
  123.           JE      COPYPATH
  124.           MOV     AL,'\'                        ;   End-of-FileSpec = '\'
  125.           STOSB
  126. COPYPATH: LODSB                                 ; Copy Rest of Parameter
  127.           OR      AL,AL                         ;   to FileSpec
  128.           JZ      COPYDONE
  129.           STOSB
  130.           JMP     SHORT COPYPATH
  131. COPYDONE: MOV     AL,'$'                        ; Set End-of-FileSpec
  132.           STOSB
  133.           MOV     DX,OFFSET FILESPEC            ; Convert to Upper Case
  134.           CALL    UPPER
  135.           MOV     AL,DRIVE                      ; Read Boot Record
  136.           MOV     CX,1
  137.           MOV     DX,0
  138.           MOV     BX,OFFSET FATBUF
  139.           INT     25H
  140.           POPF
  141.           MOV     AX,FATBUF[11]                 ; Read Sector Size
  142.           MOV     SECSIZE,AX                    ;   and Save
  143.           MOV     AL,BYTE PTR FATBUF[13]        ; Read Sectors per Cluster
  144.           XOR     AH,AH
  145.           MOV     CLSTSEC,AX                    ;   and Save
  146.           MOV     CX,FATBUF[14]                 ; Read # of Reserved Sectors
  147.           MOV     AL,BYTE PTR FATBUF[16]        ; Read # of FAT's
  148.           XOR     AH,AH                         ; Convert to Word
  149.           MOV     BX,FATBUF[22]                 ; Read Sectors per FAT
  150.           MOV     FATSEC,BX
  151.           MUL     BX                            ; Calculate Total FAT Sectors
  152.           ADD     CX,AX                         ; Add to Reserved Sectors
  153.           MOV     AX,FATBUF[17]                 ; Read Number of DIR Entries
  154.           MOV     DIR_LEN,AX
  155.           PUSH    CX                            ; Calculate DIR Sectors
  156.           MOV     CL,5
  157.           SHL     AX,CL
  158.           POP     CX
  159.           MOV     BX,SECSIZE
  160.           XOR     DX,DX
  161.           DIV     BX
  162.           OR      DX,DX                         ; Adjust for Partial Sector
  163.           JZ      NO_ADD
  164.           INC     AX
  165. NO_ADD:   MOV     DIRSEC,AX                     ; Save DIR Sectors
  166.           ADD     CX,AX                         ; Add DIR Sectors to Reserved
  167.           MOV     STARTSEC,CX                   ; Save in STARTSEC
  168.           MOV     AX,FATSEC                     ; Calculate FAT Buffer Size
  169.           MOV     BX,SECSIZE
  170.           MUL     BX
  171.           MOV     BX,AX
  172.           LEA     AX,FATBUF[BX]                 ; Get DIR Buffer Pointer
  173.           MOV     DIRBUF,AX
  174.           MOV     AX,FATBUF[19]                 ; Read Total Sectors on Media
  175.           SUB     AX,CX                         ; Calculate Total Data Clusters
  176.           MOV     BX,CLSTSEC
  177.           XOR     DX,DX
  178.           DIV     BX
  179.           CMP     AX,4079                       ; If Necessary, Adjust FAT Size
  180.           JLE     FAT_OK
  181.           MOV     FATSIZE,4
  182.           MOV     EOF,0FFF8H
  183. FAT_OK:   MOV     AL,DRIVE                      ; Read FAT
  184.           MOV     CX,FATSEC
  185.           MOV     DX,1
  186.           MOV     BX,OFFSET FATBUF
  187.           INT     25H
  188.           POPF
  189.           MOV     AL,DRIVE                      ; Read Root Directory
  190.           MOV     CX,DIRSEC
  191.           MOV     DX,STARTSEC
  192.           SUB     DX,CX
  193.           MOV     BX,DIRBUF
  194.           INT     25H
  195.           POPF
  196.           MOV     SI,OFFSET FILESPEC[3]         ; Point to First Element of Path
  197. NEXT_FLD: MOV     DI,OFFSET FILENAME            ; Point to FileName Buffer
  198. NEXTCHAR: LODSB                                 ; Copy Path Element to FileName
  199.           CMP     AL,'\'                        ;   until '\' or '$'
  200.           JE      GOT_DIR
  201.           CMP     AL,'$'
  202.           JE      GOT_FNM
  203.           STOSB
  204.           JMP     SHORT NEXTCHAR
  205. GOT_DIR:  MOV     AL,0                          ; If '\', Read Subdirectory
  206.           STOSB
  207.           CALL    READDIR
  208.           JNC     NEXT_FLD                      ;   If No Error, Get Next Dir
  209.           JMP     ERROR                         ;   Else Flag Error
  210. GOT_FNM:  MOV     AL,0                          ; If '$',
  211.           STOSB
  212.           CALL    SRCHFILE                      ;   Read File DIR Info
  213.           JNC     NO_ERR3
  214.           JMP     ERROR                         ; If Error, Say So
  215. NO_ERR3:  MOV     AX,[BX+28]                    ; Read File Length
  216.           MOV     SIZLSB,AX
  217.           MOV     DX,[BX+30]
  218.           MOV     SIZMSB,AX
  219.           MOV     DI,OFFSET CHAINMSG6[31]       ; Convert to ASCII
  220.           CALL    DEC8OUT                       ; Strip Off Leading Zeroes
  221.           CALL    STRIP0
  222.           MOV     AH,9                          ; Output FileSpec Message
  223.           MOV     DX,OFFSET CHAINMSG1
  224.           INT     21H
  225.           MOV     AH,9
  226.           MOV     DX,OFFSET FILESPEC
  227.           INT     21H
  228.           MOV     AH,9
  229.           MOV     DX,OFFSET CHAINMSG2
  230.           INT     21H
  231.           MOV     BX,[BX+26]                    ; Read Starting Cluster Number
  232.           XOR     CX,CX                         ; Cluster Count = 0
  233.           OR      BX,BX                         ; If Start Cluster = 0, Done
  234.           JZ      LASTCLST
  235.           MOV     AX,BX                         ; Output First Cluster Number
  236.           CALL    OUT_CLST
  237.           MOV     PREV,BX                       ; Previous Cluster = First
  238.           INC     CX                            ; Cluster Count = 1
  239.           CALL    NEXTCLST                      ; Get Next Cluster Number
  240.           CMP     BX,EOF                        ; If Last, Skip
  241.           JNB     LASTCLST
  242. CLSTLOOP: INC     CX                            ; Increment Cluster Count
  243.           MOV     AX,PREV                       ; If Cluster is Previous + 1,
  244.           INC     AX
  245.           CMP     AX,BX
  246.           JNE     CLSTOUT
  247.           MOV     RANGE,-1                      ;   Set Range Flag
  248.           JMP     SHORT NEXTONE
  249. CLSTOUT:  CMP     RANGE,0                       ; Else
  250.           JE      NORANGE                       ;   If Range Flag is Set, 
  251.           MOV     AH,9                          ;     Output " - "
  252.           MOV     DX,OFFSET THRUSTR
  253.           INT     21H
  254.           MOV     AX,PREV                       ;     Output Last Clstr in Range
  255.           CALL    OUT_CLST
  256.           MOV     RANGE,0                       ;     Reset Range Flag
  257. NORANGE:  MOV     AH,9                          ;   Output ",  "
  258.           MOV     DX,OFFSET ANDSTR
  259.           INT     21H
  260.           MOV     AX,BX                         ; Output Cluster Number
  261.           CALL    OUT_CLST
  262. NEXTONE:  MOV     PREV,BX                       ; Previous = Current
  263.           CALL    NEXTCLST                      ; Get Next Cluster Number
  264.           CMP     BX,EOF                        ; If Not EOF, Repeat
  265.           JB      CLSTLOOP
  266.           CMP     RANGE,0                       ; If Range Flag is Set,
  267.           JE      LASTCLST
  268.           MOV     AH,2                          ;   Output " - "
  269.           MOV     DL,'-'
  270.           INT     21H
  271.           MOV     AX,PREV                       ;   Output Last Cluster of Range
  272.           CALL    OUT_CLST
  273. LASTCLST: MOV     AX,SIZMSB                     ; If Size = 0, 100% Waste
  274.           OR      AX,SIZLSB
  275.           JNZ     NOT_ZERO
  276.           MOV     SI,OFFSET PRCNT100
  277.           MOV     DI,OFFSET PERCENT
  278.           MOV     CX,5
  279.           REP     MOVSB
  280.           JMP     SHORT CLSTCNT
  281. NOT_ZERO: MOV     AX,SECSIZE                    ; Calculate Percent Waste
  282.           MOV     BX,CLSTSEC
  283.           MUL     BX
  284.           MOV     BX,AX
  285.           MUL     CX
  286.           SUB     AX,SIZLSB
  287.           MOV     DX,100
  288.           MUL     DX
  289.           DIV     BX
  290.           PUSH    DX
  291.           XOR     DX,DX
  292.           DIV     CX
  293.           PUSH    DX
  294.           MOV     DI,OFFSET PERCENT[2]          ; Convert Percent to ASCII
  295.           CALL    DEC2OUT
  296.           CALL    STRIP0
  297.           POP     AX
  298.           MUL     BX
  299.           POP     DI
  300.           ADD     AX,DI
  301.           ADC     DX,0
  302.           DIV     CX
  303.           MOV     DX,100
  304.           MUL     DX
  305.           DIV     BX
  306.           MOV     DI,OFFSET PERCENT[5]
  307.           CALL    DEC2OUT
  308. CLSTCNT:  MOV     AX,CX                         ; Convert Cluster Count to ASCII
  309.           MOV     DI,OFFSET CHAINMSG4[31]
  310.           CALL    DEC5OUT
  311.           CALL    STRIP0                        ; Strip Off Leading Zeroes
  312.           MOV     AX,CLSTSEC                    ; Calculate Physical File Size
  313.           MUL     CX
  314.           MOV     CX,SECSIZE
  315.           MUL     CX
  316.           MOV     DI,OFFSET CHAINMSG5[31]       ; Convert to ASCII
  317.           CALL    DEC8OUT
  318.           CALL    STRIP0                        ; Strip Off Leading Zeroes
  319.           MOV     AH,9                          ; Output Trailer Message
  320.           MOV     DX,OFFSET CHAINMSG3
  321.           INT     21H
  322.           MOV     AX,4C00H                      ; Exit to DOS
  323.           INT     21H
  324. ERROR:    MOV     AH,9                          ; Output Error Message
  325.           MOV     DX,OFFSET SPECERR
  326.           INT     21H
  327.           MOV     AH,9
  328.           MOV     DX,OFFSET FILESPEC            ; Output FileSpec
  329.           INT     21H
  330.           MOV     AH,9
  331.           MOV     DX,OFFSET CRLF
  332.           INT     21H
  333.           MOV     AX,4C01H                      ; Exit to DOS
  334.           INT     21H
  335.  
  336. SRCHFILE: PUSH    AX                            ; Save Register
  337.           PUSH    CX
  338.           PUSH    DI
  339.           PUSH    SI
  340.           CMP     FILENAME,'.'                  ; If Filename Starts with '.',
  341.           JNE     SRCHFIL2
  342.           MOV     SI,OFFSET FILENAME            ;   Copy Filename to FCB
  343.           MOV     DI,OFFSET FCB[1]
  344.           MOV     CX,11
  345. SRCHFIL1: LODSB
  346.           STOSB
  347.           OR      AL,AL
  348.           LOOPNZ  SRCHFIL1
  349.           INC     CX                            ;   and Pad With Spaces
  350.           DEC     DI
  351.           MOV     AL,' '
  352.           REP     STOSB
  353.           JMP     SHORT SRCHFIL3
  354. SRCHFIL2: MOV     AX,2900H                      ; Else Parse Filename
  355.           MOV     SI,OFFSET FILENAME
  356.           MOV     DI,OFFSET FCB
  357.           INT     21H
  358. SRCHFIL3: MOV     DI,OFFSET FCB[1]              ; Point to Filename in FCB
  359.           MOV     SI,DIRBUF                     ; Point to Start of DIRBUF
  360.           MOV     CX,DIR_LEN                    ; Load DIR Length
  361.           JCXZ    SRCHFIL5                      ; If Zero, Not Found
  362. SRCHFIL4: PUSH    CX                            ; Save Registers
  363.           PUSH    DI
  364.           PUSH    SI
  365.           MOV     CX,11                         ; Compare Filename
  366.           REPE    CMPSB
  367.           POP     SI                            ; Restore Registers
  368.           POP     DI
  369.           POP     CX
  370.           JE      SRCHFIL6                      ; If Match, Found
  371.           ADD     SI,32                         ; Else Next DIR Entry
  372.           LOOP    SRCHFIL4                      ; and Repeat
  373. SRCHFIL5: STC                                   ; Set Error Flag
  374.           JMP     SHORT SRCHFIL7                ; Done
  375. SRCHFIL6: MOV     BX,SI                         ; Set Pointer to DIR Entry
  376.           CLC                                   ; Clear Error Flag
  377. SRCHFIL7: POP     SI                            ; Restore Registers
  378.           POP     DI
  379.           POP     CX
  380.           POP     AX
  381.           RET                                   ; Done
  382.  
  383. READDIR:  PUSH    CX                            ; Save Registers
  384.           PUSH    DI
  385.           PUSH    SI
  386.           CALL    SRCHFILE                      ; Search for DIR
  387.           JC      READDIR2                      ; If Not Found, Error
  388.           MOV     BX,[BX+26]                    ; Get Starting Cluster Number
  389.           MOV     DIR_LEN,0                     ; DIR Length = 0
  390.           OR      BX,BX                         ; If Start Cluster = 0, Error
  391.           JZ      READDIR2
  392.           MOV     AX,SECSIZE                    ; Calculate DIR Entries/Cluster
  393.           MOV     CX,CLSTSEC
  394.           MUL     CX
  395.           MOV     CL,5
  396.           SHR     AX,CL
  397.           MOV     CX,AX
  398.           MOV     DI,DIRBUF                     ; Point to DIR Buffer
  399. READDIR1: CALL    READCLST                      ; Read Cluster
  400.           ADD     DIR_LEN,CX                    ; Increment DIR Length
  401.           CMP     BX,EOF                        ; If Not Last Cluster,
  402.           JB      READDIR1                      ;   Get Next Cluster
  403.           JMP     SHORT READDIR3                ; Done Reading DIR
  404. READDIR2: STC                                   ; Set Error Flag
  405. READDIR3: POP     SI                            ; Restore Registers
  406.           POP     DI
  407.           POP     CX
  408.           RET                                   ; Done
  409.  
  410. READCLST: PUSH    AX                            ; Save Registers
  411.           PUSH    CX
  412.           PUSH    DX
  413.           MOV     AX,BX                         ; Calculate Absolute Sector #
  414.           SUB     AX,2
  415.           MOV     CX,CLSTSEC
  416.           MUL     CX
  417.           ADD     AX,STARTSEC
  418.           MOV     DX,AX
  419.           MOV     AL,DRIVE
  420.           PUSH    BX                            ; Save Registers
  421.           PUSH    DI
  422.           MOV     BX,DI                         ; Read Cluster
  423.           INT     25H
  424.           POPF
  425.           POP     DI                            ; Restore Registers
  426.           POP     BX
  427.           CALL    NEXTCLST                      ; Get Next Cluster Number
  428.           MOV     AX,CLSTSEC                    ; Increment Buffer Pointer
  429.           MOV     CX,SECSIZE
  430.           MUL     CX
  431.           ADD     DI,AX
  432.           POP     DX                            ; Restore Registers
  433.           POP     CX
  434.           POP     AX
  435.           RET                                   ; Done
  436.  
  437. NEXTCLST: CMP     FATSIZE,3                     ; If FAT Size = 16 Bits,
  438.           JE      NEXTCLS1
  439.           SHL     BX,1                          ;   Simply Read Next Cluster #
  440.           MOV     BX,FATBUF[BX]
  441.           RET                                   ;   Done
  442. NEXTCLS1: PUSH    AX                            ; Save Registers
  443.           PUSH    CX
  444.           MOV     AX,BX                         ; Word # = Cluster # * 1.5
  445.           SHL     AX,1
  446.           ADD     BX,AX
  447.           SHR     BX,1
  448.           MOV     BX,FATBUF[BX]
  449.           JNC     NEXTCLS2                      ; If Odd, Use 12 MSB's
  450.           MOV     CL,4
  451.           SHR     BX,CL
  452. NEXTCLS2: AND     BX,0FFFH                      ; Else Use 12 LSB's
  453.           POP     CX                            ; Restore Registers
  454.           POP     AX
  455.           RET                                   ; Done
  456.  
  457. UPPER:    PUSH    AX                            ; Save Registers
  458.           PUSH    DX
  459.           PUSH    DI
  460.           PUSH    SI
  461.           MOV     SI,DX                         ; Set Up Source Index
  462.           MOV     DI,DX                         ; Set Up Destination Index
  463. UPPER1:   LODSB                                 ; Read From Source
  464.           OR      AL,AL                         ; If EOS, Done
  465.           JZ      UPPER3
  466.           CMP     AL,'a'                        ; If Lower Case,
  467.           JL      UPPER2
  468.           CMP     AL,'z'
  469.           JG      UPPER2
  470.           SUB     AL,'a'-'A'                    ;   Convert to Upper Case
  471. UPPER2:   STOSB                                 ; Save in Destination
  472.           JMP     SHORT UPPER1                  ; Repeat
  473. UPPER3:   POP     SI                            ; Restore Registers
  474.           POP     DI
  475.           POP     DX
  476.           POP     AX
  477.           RET                                   ; Done
  478.  
  479. OUT_CLST: PUSH    AX                            ; Save Registers
  480.           PUSH    DX
  481.           PUSH    DI
  482.           MOV     DI,OFFSET CLSTSTR[5]          ; Convert Cluster # to Decimal
  483.           CALL    DEC5OUT
  484.           CALL    STRIP0                        ; Strip Off Leading Zeroes
  485.           MOV     AH,9                          ; Output Cluster Number
  486.           MOV     DX,OFFSET CLSTSTR
  487.           INT     21H
  488.           POP     DI                            ; Restore Registers
  489.           POP     DX
  490.           POP     AX
  491.           RET                                   ; Done
  492.  
  493. STRIP0:   CMP     BYTE PTR [DI],'0'             ; If Character != '0', Done
  494.           JNE     STRIP1
  495.           CMP     BYTE PTR [DI+1],'0'           ; If Next Character != Digit,
  496.           JL      STRIP1                        ;   Done
  497.           CMP     BYTE PTR [DI+1],'9'
  498.           JG      STRIP1
  499.           MOV     BYTE PTR [DI],' '             ; Change '0' to ' '
  500.           INC     DI                            ; Point to Next Character
  501.           JMP     SHORT STRIP0                  ; Repeat
  502. STRIP1:   RET                                   ; Done
  503.  
  504. DEC2OUT:  PUSH    AX                            ; Save Registers
  505.           PUSH    BX
  506.           XOR     AH,AH                         ; Clear AH
  507.           MOV     BL,10                         ; AH=AX%10,AL=AX/10
  508.           DIV     BL
  509.           ADD     AX,'00'                       ; Convert to ASCII
  510.           SUB     DI,2
  511.           MOV     [DI],AX                       ; Store in String
  512.           POP     BX                            ; Restore Registers
  513.           POP     AX
  514.           RET                                   ; Done
  515.  
  516. DEC4OUT:  PUSH    AX                            ; Save Registers
  517.           PUSH    BX
  518.           MOV     BL,100                        ; AH=AX%100,AL=AX/100
  519.           DIV     BL
  520.           XCHG    AH,AL                         ; Convert 2 LSD's
  521.           CALL    DEC2OUT
  522.           XCHG    AH,AL                         ; Convert 2 MSD's
  523.           CALL    DEC2OUT
  524.           POP     BX                            ; Restore Registers
  525.           POP     AX
  526.           RET                                   ; Done
  527.  
  528. DEC5OUT:  PUSH    AX                            ; Save Registers
  529.           PUSH    BX
  530.           PUSH    DX                            ; DX=AX%10000,AX=AX/10000
  531.           MOV     BX,10000
  532.           XOR     DX,DX
  533.           DIV     BX
  534.           XCHG    DX,AX                         ; Convert 4 LSD's
  535.           CALL    DEC4OUT
  536.           XCHG    DX,AX                         ; Convert MSD
  537.           ADD     AL,'0'
  538.           SUB     DI,1
  539.           MOV     [DI],AL
  540.           POP     DX                            ; Restore Registers
  541.           POP     BX
  542.           POP     AX
  543.           RET                                   ; Done
  544.  
  545. DEC8OUT:  PUSH    AX                            ; Save Registers
  546.           PUSH    BX
  547.           PUSH    DX
  548.           MOV     BX,10000                      ; DX=DX:AX%10000,AX=DX:AX/10000
  549.           DIV     BX
  550.           XCHG    DX,AX                         ; Convert 4 LSD's
  551.           CALL    DEC4OUT
  552.           XCHG    DX,AX                         ; Convert 4 MSD's
  553.           CALL    DEC4OUT
  554.           POP     DX                            ; Restore Registers
  555.           POP     BX
  556.           POP     AX
  557.           RET                                   ; Done
  558.  
  559. FATBUF    LABEL   WORD
  560.  
  561. CODE      ENDS
  562.  
  563.           END     CHAIN
  564.