home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast.iso / pcmag / vol6n02.zip / SCANDIR.ASM < prev    next >
Assembly Source File  |  1987-12-13  |  22KB  |  428 lines

  1.  
  2. ;            Scandir.asm
  3. ; FORMAT: SCANDIR [directory] [directory]
  4.  
  5. CODE SEGMENT                           ;*************************;
  6. ASSUME CS:CODE,DS:CODE                 ;*                       *;
  7. ORG 100H                               ;*  REMEMBER TO EXE2BIN  *;
  8.                                        ;*                       *;
  9. START:         JMP    BEGINNING        ;*************************;
  10.  
  11. ;              DATA AREA
  12. ;              ---------
  13. DOS_DIRECTIVE  DB  "\COMMAND.COM",0
  14. PARAMETER      DB  127,'/C DIR '
  15. DIR_PATH       DB  110 DUP(32)
  16. DIR_FILE       DB  '>DIR.$$$',13
  17.  
  18. ENVIRONMENT    DW  0
  19. COM_LINE_PTR   DD  OFFSET PARAMETER
  20. STACK_SEG      DW  ?
  21. STACK_PTR      DW  ?
  22.  
  23. PARA_FLAG      DB  0
  24. STATUS_REG     DW  ?
  25. BUFFER_ADDR    DW  OFFSET BUFFER
  26.  
  27. DIR_OFFSET1    DW  ?
  28. DIR_OFFSET2    DW  ?
  29. CUR_OFFSET1    DW  ?
  30. CUR_OFFSET2    DW  ?
  31. LEFT           DB  1
  32. RIGHT          DB  0
  33.  
  34. STATUS_LINE    DB  'Use ',24,32,25,32,27,32,26,' PgUp PgDn Scroll Lock  '
  35. ACTIVE         DB  24,' Active ',24,9 DUP(32),'Press Esc to Exit',7 DUP(32)
  36.  
  37. ERROR_MSG      DB  13,10,'COMMAND.COM must be in drive A:$'
  38.  
  39.                DB  'Copyright 1986 Ziff Davis Publishing Co.',1AH
  40.                DB  'Michael J. Mefford'
  41.  
  42. ;-------------------------------------------------------------------------;
  43. ; Some housekeeping first. Free up excess memory allocated to us. We then ;
  44. ; can load COMMAND.COM and let it do the work of getting the directories. ;
  45. ; Also, zero out the buffer where the directories will be stored.         ;
  46. ;-------------------------------------------------------------------------;
  47.  
  48. ;              CODE AREA
  49. ;              ---------
  50. BEGINNING:
  51.                MOV    BX,1000H         ;Request 4096 paragraphs (64K) for us
  52.                MOV    AH,4AH           ; and return the rest to the pool
  53.                INT    21H              ; to load COMMAND.COM
  54.  
  55. ZERO_BUFFER:   MOV    DI,OFFSET BUFFER ;Put zeros in the 60,000 byte directory
  56.                MOV    CX,30000         ; buffer at the end of our code. This
  57.                XOR    AX,AX            ; will eliminate the garbage that would
  58.                CLD                     ; be displayed at the end of directory.
  59.                REP STOSW
  60.  
  61. ;-------------------------------------------------------------;
  62. ; This routine will parse the parameters of the command line. ;
  63. ;-------------------------------------------------------------;
  64.  
  65. PARSE:         MOV    SI,81H           ;Point to first character in parameters
  66.                MOV    BP,2                 ; and a count of two possible char.
  67. NEXT_PARA:     MOV    DI,OFFSET DIR_PATH   ;Point to parameter storage.
  68. GET_PARA:      LODSB                       ;Get a character.
  69.                CMP    AL,13            ;If it's carriage return, then end of
  70.                JNZ    SPACE            ; of parameters.
  71.                CMP    PARA_FLAG,1      ;If parameter flag is high, we have
  72.                JZ     DONE_HERE1       ; already written directory, else do so
  73.                CALL   WRITE_DIR        ; now and then we are ready to display.
  74. DONE_HERE1:    JMP    DISPLAY
  75. SPACE:         CMP    AL,32            ;If there is more than one space
  76.                JZ     GET_PARA         ; between parameters, get next char.
  77.  
  78. STORE_CHAR:    STOSB                   ;Store the character
  79.                LODSB                   ; and get another.
  80.                CMP    AL,13            ; If it's carriage return, it is the
  81.                JZ     DONE_HERE2       ; the end of parameters.
  82.                CMP    AL,32            ;If it's space, it's the end of this
  83.                JNZ    STORE_CHAR       ; parameter, otherwise store the char.
  84.                PUSH   SI               ;Save pointers.
  85.                PUSH   DI
  86.                CALL   WRITE_DIR        ;Write the directory and on return, see
  87.                POP    DI               ;Restore pointers.
  88.                POP    SI
  89.                DEC    BP               ; if this is second parameter.
  90.                JNZ    NEXT_PARA        ;If no, get next parameter, else we are
  91.                JMP    SHORT DISPLAY    ; ready to display.
  92. DONE_HERE2:    CALL   WRITE_DIR
  93.  
  94. ;---------------------------------------------------------------------;
  95. ; More housekeeping. We will be writing directly to the screen buffer ;
  96. ; so we need the display card address and the status register.        ;
  97. ; Turn off the cursor; it is not needed and would be distracting.     ;
  98. ; Also, clear the screen with the current attribute. This will please ;
  99. ; those who have a customized color screen.                           ;
  100. ;---------------------------------------------------------------------;
  101.  
  102. DISPLAY:       MOV    AX,40H           ;Point to the ROM BIOS data area
  103.                MOV    DS,AX            ; and get base address of active
  104.                MOV    AX,DS:[63H]      ; display card.
  105.                ADD    AX,6             ;Add six to get status register
  106.                PUSH   CS               ;Done there, so restore data segment.
  107.                POP    DS
  108.                MOV    STATUS_REG,AX    ;Store status register.
  109.                MOV    BX,0B000H        ;Assume that it is the B&W card.
  110.                CMP    AX,3BAH          ;Status port of MONO card is 3BAh.
  111.                JZ     MONO             ;If that's what we got, it's MONO
  112.                ADD    BX,800H          ; else COLOR so add 800h.
  113. MONO:          MOV    ES,BX
  114.  
  115.                MOV    CX,2000H         ;Turn off the cursor.
  116.                MOV    AH,1
  117.                INT    10H
  118.                CALL   CLS              ;Clear the screen.
  119.  
  120. ;--------------------------------------------;
  121. ; Now, we are ready to initialize the screen ;
  122. ; with the two directories and status line.  ;
  123. ;--------------------------------------------;
  124.  
  125.                MOV    AH,3                 ;Set counter to three.
  126.                MOV    SI,OFFSET BUFFER     ;Point to buffer.
  127.                MOV    DI,0                 ;Point to top left of screen.
  128.                CALL   WRITE_LINE           ;We're set up, so write to screen.
  129.                CMP    BYTE PTR [SI],32     ;Is directory more than one line?
  130.                JNZ    STORE_OFFSET1        ;If no, store pointer
  131.                ADD    SI,39                ; else adjust by one line.
  132. STORE_OFFSET1: MOV    DIR_OFFSET1,SI       ;SI now points to first line of
  133.                MOV    CUR_OFFSET1,SI       ; directory; save.
  134.                MOV    AH,20                ;Set counter to first 20 lines
  135.                CALL   WRITE_LINE           ; and display.
  136.  
  137.                MOV    AH,3
  138.                MOV    SI,OFFSET BUFFER+30000         ;Do the same for the
  139.                MOV    DI,82                          ;second directory.
  140.                CALL   WRITE_LINE
  141.                CMP    BYTE PTR [SI],32
  142.                JNZ    STORE_OFFSET2
  143.                ADD    SI,39
  144. STORE_OFFSET2: MOV    DIR_OFFSET2,SI
  145.                MOV    CUR_OFFSET2,SI
  146.                MOV    AH,20
  147.                CALL   WRITE_LINE
  148.  
  149.                MOV    AH,2                           ;And the same for the
  150.                MOV    SI,OFFSET STATUS_LINE          ;status line.
  151.                MOV    DI,160*24
  152. NEXT_STAT:     CALL   WRITE_SCREEN
  153.                SUB    DI,82
  154.                DEC    AH
  155.                JNZ    NEXT_STAT
  156.  
  157. ;-----------------------------------------;
  158. ; We are ready for business now. We will  ;
  159. ; loop here, waiting for user keystrokes. ;
  160. ;-----------------------------------------;
  161.  
  162. GET_KEY:       MOV    AH,2                 ;Get the current shift status.
  163.                INT    16H
  164.                TEST   AL,10H               ;Is Scroll Lock on?
  165.                JZ     NOT_SCR_LOCK
  166.                MOV    AH,24                ;If yes, store an up arrow
  167.                MOV    ACTIVE,AH            ; on both sides of ACTIVE
  168.                MOV    ACTIVE+9,AH
  169.                JMP    SHORT SHOW_STATUS    ; and display.
  170.  
  171. NOT_SCR_LOCK:  MOV    AH,24                ;If no, assume left is active.
  172.                CMP    LEFT,1               ;If it is, store an up arrow
  173.                JZ     ON_LEFT              ; to the left of ACTIVE
  174.                MOV    AH,32                ; else a space.
  175. ON_LEFT:       MOV    ACTIVE,AH
  176.                MOV    AH,24                ;Do the same for the right side.
  177.                CMP    RIGHT,1
  178.                JZ     ON_RIGHT
  179.                MOV    AH,32
  180. ON_RIGHT:      MOV    ACTIVE+9,AH
  181.  
  182. SHOW_STATUS:   MOV    SI,OFFSET ACTIVE     ;Update the status line.
  183.                MOV    DI,24*160+70
  184.                CALL   WRITE_SCREEN
  185.  
  186.                MOV    AH,1                 ;See if an ASCII character is
  187.                INT    16H                  ; available to be read.
  188.                JZ     GET_KEY              ;If not, see if Scroll Lock has
  189.                MOV    AH,0                 ; been toggled, else get the
  190.                INT    16H                  ; keystroke.
  191.  
  192. ESC:           CMP    AH,1                     ;Is it Esc?
  193.                JNZ    UP_ARROW
  194.                MOV    DX,OFFSET DIR_FILE+1     ;If yes, make our temporary
  195.                MOV    BYTE PTR[DIR_FILE+8],0   ; file, DIR.$$$, into a ASCIIZ
  196.                MOV    AH,41H                   ; and delete it.
  197.                INT    21H
  198.                CALL   CLS                      ;Clear the screen.
  199.                MOV    CX,607H                  ;Turn the cursor back on
  200.                MOV    AH,1
  201.                INT    10H
  202.                INT    20H                      ; and exit.
  203.  
  204. UP_ARROW:      CMP    AH,48H
  205.                JNZ    DN_ARROW             ;If UP ARROW, scroll down
  206.                MOV    BP,-39               ; one line.
  207.                CALL   SCROLL
  208.  
  209. DN_ARROW:      CMP    AH,50H
  210.                JNZ    PG_UP                ;If DOWN ARROW, scroll up
  211.                MOV    BP,39                ; one line.
  212.                CALL   SCROLL
  213.  
  214. PG_UP:         CMP    AH,49H
  215.                JNZ    PG_DN                ;If PgUp, scroll down
  216.                MOV    BP,-39*20            ; 20 lines.
  217.                CALL   SCROLL
  218.  
  219. PG_DN:         CMP    AH,51H
  220.                JNZ    LF_ARROW             ;If PgDn, scroll up
  221.                MOV    BP,39*20             ; 20 lines.
  222.                CALL   SCROLL
  223.  
  224. LF_ARROW:      CMP    AH,4BH
  225.                JNZ    RT_ARROW             ;If LEFT ARROW,
  226.                AND    RIGHT,0              ; turn right off
  227.                OR     LEFT,1               ; and left on.
  228.  
  229. RT_ARROW:      CMP    AH,4DH
  230.                JNZ    NEXT_KEY             ;If RIGHT ARROW,
  231.                AND    LEFT,0               ; turn left off
  232.                OR     RIGHT,1              ; and right on
  233.  
  234. NEXT_KEY:      JMP    GET_KEY
  235.  
  236. ;---------------------------------------------------------------------;
  237. ; This subroutine will load COMMAND.COM/C DIR [directory] > DIR.$$$   ;
  238. ; On return, the file, DIR.$$$ will be opened, read and closed.       ;
  239. ; The directory will be formated without CR's and LF's.  Entry lines  ;
  240. ; without a time will be padded with spaces.  The directory parameter ;
  241. ; will be zeroed out, in preparation of the next directory parameter. ;
  242. ;---------------------------------------------------------------------;
  243.  
  244. WRITE_DIR:     OR     PARA_FLAG,1
  245.                MOV    DX,OFFSET DOS_DIRECTIVE      ;Set up the parameter
  246.                MOV    BX,OFFSET ENVIRONMENT        ; block for the load.
  247.                MOV    WORD PTR COM_LINE_PTR+2,DS
  248.  
  249.                PUSH   DS                   ;When control is returned from
  250.                PUSH   ES                   ; the load, all registers will
  251.                PUSH   BP                   ; be changed, including SS and SP.
  252.                CLI
  253.                MOV    CS:STACK_SEG,SS      ;We, therefore, are responsible
  254.                MOV    CS:STACK_PTR,SP      ; for saving any registers whose
  255.                STI                         ; values are important to us.
  256.                MOV    AX,4B00H
  257.                INT    21H                  ;Load COMMAND.COM/C
  258.                CLI
  259.                MOV    SP,CS:STACK_PTR      ;We are back in control.
  260.                MOV    SS,CS:STACK_SEG      ;Restore registers.
  261.                STI
  262.                POP    BP
  263.                POP    ES
  264.                POP    DS
  265.                JNC    OPEN_DIR             ;If carry flag is set, COMMAND.COM
  266.                MOV    DX,OFFSET ERROR_MSG  ; was not found; inform the user
  267.                MOV    AH,9
  268.                INT    21H
  269.                INT    20H                  ; and exit
  270.  
  271. OPEN_DIR:      MOV    BYTE PTR[DIR_FILE+8],0     ;else, open the file
  272.                MOV    DX,OFFSET DIR_FILE+1       ; DIR.$$$
  273.                MOV    AX,3D02H                   ; for reading.
  274.                INT    21H
  275.  
  276. READ_DIR:      MOV    BX,AX                      ;File handle in BX.
  277.                MOV    DX,BUFFER_ADDR             ;Point to our buffer.
  278.                MOV    DI,DX                      ;Save destination.
  279.                ADD    DX,1000                    ;Leave room to format.
  280.                MOV    SI,DX                      ;Start of file.
  281.                ADD    SI,2                       ;Bump past CR and LF.
  282.                MOV    CX,30000                   ;Attempt to read up to
  283.                MOV    AH,3FH                     ; 30,000 bytes; that's
  284.                INT    21H                        ; half of our buffer.
  285.                ADD    BUFFER_ADDR,30000          ;Adjust buffer for next read.
  286.                SUB    AX,2                       ;Adjust bytes read
  287.                MOV    DX,AX                      ; and save.
  288.  
  289. CLOSE_DIR:     MOV    AH,3EH                     ;Close file.
  290.                INT    21H
  291.                MOV    BYTE PTR[DIR_FILE+8],0DH
  292.  
  293.                XOR    BX,BX                      ;Zero in byte counter.
  294. NEXT_LINE:     MOV    CX,39                      ;39 byte lines.
  295. GET_BYTE:      LODSB                             ;Get a byte.
  296.                CMP    AL,13                      ;Is it carriage return?
  297.                JZ     STORE_BLANK                ;If yes, pad with spaces.
  298.                STOSB                             ;Else store the byte.
  299.                INC    BX                         ;Increment byte counter.
  300.                LOOP   GET_BYTE                   ;Get rest of line.
  301.                JMP    SHORT CK_CR_LF             ;Check for CR and LF.
  302.  
  303. STORE_BLANK:   MOV    AL,32                      ;Pad the balance of the
  304.                REP    STOSB                      ; line with spaces.
  305.                DEC    SI
  306.  
  307. CK_CR_LF:      CMP    BYTE PTR [SI],13           ;Line end with CR?
  308.                JNZ    CK_DIR_END                 ;If no, check if end of DIR.
  309.                ADD    SI,2                       ;Else, bump past CR and LF.
  310.                ADD    BX,2                       ;Adjust byte counter.
  311. CK_DIR_END:    CMP    BX,DX                      ;Are we end of DIR?
  312.                JB     NEXT_LINE                  ;If no, get next line.
  313.  
  314.                MOV    CX,800                     ;Pad end of DIR with null
  315.                MOV    AL,0                       ; characters as end of DIR
  316.                REP    STOSB                      ; signature.
  317.  
  318. ZERO_PATH:     MOV    CX,110                     ;Zero out the directory
  319.                MOV    DI,OFFSET DIR_PATH         ; path in preparation
  320.                MOV    AL,32                      ; of the next parameter.
  321.                REP    STOSB
  322.                RET                               ;And return.
  323.  
  324. ;---------------------------------------------------;
  325. ; This subroutine will check to see if the left     ;
  326. ; or right or both directories, should be scrolled. ;
  327. ; The boundaries of the directories will be checked ;
  328. ; in order to keep them on the screen.              ;
  329. ;---------------------------------------------------;
  330.  
  331. SCROLL:        CMP    BYTE PTR ACTIVE,24   ;Is the left side active?
  332.                JNZ    CK_RIGHT             ;If no, check right side
  333.                MOV    SI,CUR_OFFSET1       ; else, get current offset
  334.                ADD    SI,BP                ; add keyboard response.
  335.                CMP    SI,DIR_OFFSET1       ;Is it below starting position?
  336.                JA     UPPER_LIMIT1         ;If yes, check upper limit
  337.                MOV    SI,DIR_OFFSET1       ; else set to starting position.
  338. UPPER_LIMIT1:  CMP    BYTE PTR[SI],0       ;Is it one of the zero bytes at
  339.                JA     OK1                  ; we stored in the buffer?
  340.                MOV    SI,DIR_OFFSET1       ;If yes, set to starting position
  341. OK1:           MOV    CUR_OFFSET1,SI       ; and the same with current.
  342.                MOV    DI,480               ;Point to directory display line.
  343.                MOV    AH,20                ;A count of 20 lines
  344.                CALL   WRITE_LINE           ; and display.
  345. CK_RIGHT:      CMP    BYTE PTR ACTIVE+9,24
  346.                JNZ    RETURN
  347.                MOV    SI,CUR_OFFSET2       ;Do the same for the right side.
  348.                ADD    SI,BP
  349.                CMP    SI,DIR_OFFSET2
  350.                JA     UPPER_LIMIT2
  351.                MOV    SI,DIR_OFFSET2
  352. UPPER_LIMIT2:  CMP    BYTE PTR[SI],0
  353.                JA     OK2
  354.                MOV    SI,DIR_OFFSET2
  355. OK2:           MOV    CUR_OFFSET2,SI
  356.                MOV    DI,562
  357.                MOV    AH,20
  358.                CALL   WRITE_LINE
  359. RETURN:        RET
  360.  
  361. ;---------------------------------------------------;
  362. ; This subroutine will display the requested lines. ;
  363. ;---------------------------------------------------;
  364.  
  365. WRITE_LINE:    CALL   WRITE_SCREEN         ;Display.
  366.                DEC    AH
  367.                JNZ    WRITE_LINE           ;Do all lines.
  368.                RET                         ;Return.
  369.  
  370. ;---------------------------------------------------------------;
  371. ; This subroutine displays the directory by writing directly    ;
  372. ; to the screen buffer. To avoid screen noise (snow) on the     ;
  373. ; color card, the horizontal retrace has to be monitored.       ;
  374. ;---------------------------------------------------------------;
  375.  
  376. WRITE_SCREEN:  MOV    DX,STATUS_REG        ;Get status register.
  377. GET_LINE:      MOV    CX,39                ;Set count to 39 characters.
  378. NEXT_BYTE:     LODSB                       ;Get a byte.
  379.                MOV    BL,AL                ;Save it in BL.
  380. HORZ_RET:      IN     AL,DX                ;Get status.
  381.                TEST   AL,1                 ;Is it low?
  382.                JNZ    HORZ_RET             ;If not, wait until it is.
  383.                CLI                         ;No more interrupts.
  384.  
  385. WAIT:          IN     AL,DX                ;Get status.
  386.                TEST   AL,1                 ;Is it high?
  387.                JZ     WAIT                 ;If no, wait until it is.
  388.                MOV    AL,BL                ;Retrieve character; now it's OK
  389.                STOSB                       ; to write to screen buffer.
  390.                STI                         ;Interrupts back on.
  391.                INC    DI                   ;Bump pointer past attribute.
  392.                LOOP   NEXT_BYTE            ;Get next byte.
  393.                ADD    DI,82                ;Point to next line.
  394.                RET                         ;Return
  395.  
  396. ;--------------------------------------------;
  397. ; This subroutine gets the current attribute ;
  398. ; and clears the screen with that attribute. ;
  399. ;--------------------------------------------;
  400.  
  401. CLS:           XOR    BH,BH                ;Get current attribute
  402.                MOV    AH,8                 ; of display page zero.
  403.                INT    10H
  404.                MOV    AL,25                ;Scroll all 25 lines.
  405.                MOV    CX,0                 ;From upper left
  406.                MOV    DX,194FH             ; to lower right.
  407.                MOV    BH,AH                ;Attribute to BH.
  408.                MOV    AH,6
  409.                INT    10H
  410.                RET                         ;Return.
  411.  
  412. ;----------------------------------------;
  413. ; This subroutine displays the messages. ;
  414. ;----------------------------------------;
  415.  
  416. DISP_STRING:   MOV    AH,9                 ;Display a string.
  417.                INT    21H
  418.                RET                         ;Return.
  419.  
  420. ;----------------------------------------------;
  421. ;  60,000 byte directory buffer at end of code.;
  422. ;----------------------------------------------;
  423.  
  424. BUFFER:
  425.  
  426. CODE ENDS
  427. END  START
  428.