home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS - Coast to Coast
/
simteldosarchivecoasttocoast.iso
/
pcmag
/
vol6n02.zip
/
SCANDIR.ASM
< prev
next >
Wrap
Assembly Source File
|
1987-12-13
|
22KB
|
428 lines
; Scandir.asm
; FORMAT: SCANDIR [directory] [directory]
CODE SEGMENT ;*************************;
ASSUME CS:CODE,DS:CODE ;* *;
ORG 100H ;* REMEMBER TO EXE2BIN *;
;* *;
START: JMP BEGINNING ;*************************;
; DATA AREA
; ---------
DOS_DIRECTIVE DB "\COMMAND.COM",0
PARAMETER DB 127,'/C DIR '
DIR_PATH DB 110 DUP(32)
DIR_FILE DB '>DIR.$$$',13
ENVIRONMENT DW 0
COM_LINE_PTR DD OFFSET PARAMETER
STACK_SEG DW ?
STACK_PTR DW ?
PARA_FLAG DB 0
STATUS_REG DW ?
BUFFER_ADDR DW OFFSET BUFFER
DIR_OFFSET1 DW ?
DIR_OFFSET2 DW ?
CUR_OFFSET1 DW ?
CUR_OFFSET2 DW ?
LEFT DB 1
RIGHT DB 0
STATUS_LINE DB 'Use ',24,32,25,32,27,32,26,' PgUp PgDn Scroll Lock '
ACTIVE DB 24,' Active ',24,9 DUP(32),'Press Esc to Exit',7 DUP(32)
ERROR_MSG DB 13,10,'COMMAND.COM must be in drive A:$'
DB 'Copyright 1986 Ziff Davis Publishing Co.',1AH
DB 'Michael J. Mefford'
;-------------------------------------------------------------------------;
; Some housekeeping first. Free up excess memory allocated to us. We then ;
; can load COMMAND.COM and let it do the work of getting the directories. ;
; Also, zero out the buffer where the directories will be stored. ;
;-------------------------------------------------------------------------;
; CODE AREA
; ---------
BEGINNING:
MOV BX,1000H ;Request 4096 paragraphs (64K) for us
MOV AH,4AH ; and return the rest to the pool
INT 21H ; to load COMMAND.COM
ZERO_BUFFER: MOV DI,OFFSET BUFFER ;Put zeros in the 60,000 byte directory
MOV CX,30000 ; buffer at the end of our code. This
XOR AX,AX ; will eliminate the garbage that would
CLD ; be displayed at the end of directory.
REP STOSW
;-------------------------------------------------------------;
; This routine will parse the parameters of the command line. ;
;-------------------------------------------------------------;
PARSE: MOV SI,81H ;Point to first character in parameters
MOV BP,2 ; and a count of two possible char.
NEXT_PARA: MOV DI,OFFSET DIR_PATH ;Point to parameter storage.
GET_PARA: LODSB ;Get a character.
CMP AL,13 ;If it's carriage return, then end of
JNZ SPACE ; of parameters.
CMP PARA_FLAG,1 ;If parameter flag is high, we have
JZ DONE_HERE1 ; already written directory, else do so
CALL WRITE_DIR ; now and then we are ready to display.
DONE_HERE1: JMP DISPLAY
SPACE: CMP AL,32 ;If there is more than one space
JZ GET_PARA ; between parameters, get next char.
STORE_CHAR: STOSB ;Store the character
LODSB ; and get another.
CMP AL,13 ; If it's carriage return, it is the
JZ DONE_HERE2 ; the end of parameters.
CMP AL,32 ;If it's space, it's the end of this
JNZ STORE_CHAR ; parameter, otherwise store the char.
PUSH SI ;Save pointers.
PUSH DI
CALL WRITE_DIR ;Write the directory and on return, see
POP DI ;Restore pointers.
POP SI
DEC BP ; if this is second parameter.
JNZ NEXT_PARA ;If no, get next parameter, else we are
JMP SHORT DISPLAY ; ready to display.
DONE_HERE2: CALL WRITE_DIR
;---------------------------------------------------------------------;
; More housekeeping. We will be writing directly to the screen buffer ;
; so we need the display card address and the status register. ;
; Turn off the cursor; it is not needed and would be distracting. ;
; Also, clear the screen with the current attribute. This will please ;
; those who have a customized color screen. ;
;---------------------------------------------------------------------;
DISPLAY: MOV AX,40H ;Point to the ROM BIOS data area
MOV DS,AX ; and get base address of active
MOV AX,DS:[63H] ; display card.
ADD AX,6 ;Add six to get status register
PUSH CS ;Done there, so restore data segment.
POP DS
MOV STATUS_REG,AX ;Store status register.
MOV BX,0B000H ;Assume that it is the B&W card.
CMP AX,3BAH ;Status port of MONO card is 3BAh.
JZ MONO ;If that's what we got, it's MONO
ADD BX,800H ; else COLOR so add 800h.
MONO: MOV ES,BX
MOV CX,2000H ;Turn off the cursor.
MOV AH,1
INT 10H
CALL CLS ;Clear the screen.
;--------------------------------------------;
; Now, we are ready to initialize the screen ;
; with the two directories and status line. ;
;--------------------------------------------;
MOV AH,3 ;Set counter to three.
MOV SI,OFFSET BUFFER ;Point to buffer.
MOV DI,0 ;Point to top left of screen.
CALL WRITE_LINE ;We're set up, so write to screen.
CMP BYTE PTR [SI],32 ;Is directory more than one line?
JNZ STORE_OFFSET1 ;If no, store pointer
ADD SI,39 ; else adjust by one line.
STORE_OFFSET1: MOV DIR_OFFSET1,SI ;SI now points to first line of
MOV CUR_OFFSET1,SI ; directory; save.
MOV AH,20 ;Set counter to first 20 lines
CALL WRITE_LINE ; and display.
MOV AH,3
MOV SI,OFFSET BUFFER+30000 ;Do the same for the
MOV DI,82 ;second directory.
CALL WRITE_LINE
CMP BYTE PTR [SI],32
JNZ STORE_OFFSET2
ADD SI,39
STORE_OFFSET2: MOV DIR_OFFSET2,SI
MOV CUR_OFFSET2,SI
MOV AH,20
CALL WRITE_LINE
MOV AH,2 ;And the same for the
MOV SI,OFFSET STATUS_LINE ;status line.
MOV DI,160*24
NEXT_STAT: CALL WRITE_SCREEN
SUB DI,82
DEC AH
JNZ NEXT_STAT
;-----------------------------------------;
; We are ready for business now. We will ;
; loop here, waiting for user keystrokes. ;
;-----------------------------------------;
GET_KEY: MOV AH,2 ;Get the current shift status.
INT 16H
TEST AL,10H ;Is Scroll Lock on?
JZ NOT_SCR_LOCK
MOV AH,24 ;If yes, store an up arrow
MOV ACTIVE,AH ; on both sides of ACTIVE
MOV ACTIVE+9,AH
JMP SHORT SHOW_STATUS ; and display.
NOT_SCR_LOCK: MOV AH,24 ;If no, assume left is active.
CMP LEFT,1 ;If it is, store an up arrow
JZ ON_LEFT ; to the left of ACTIVE
MOV AH,32 ; else a space.
ON_LEFT: MOV ACTIVE,AH
MOV AH,24 ;Do the same for the right side.
CMP RIGHT,1
JZ ON_RIGHT
MOV AH,32
ON_RIGHT: MOV ACTIVE+9,AH
SHOW_STATUS: MOV SI,OFFSET ACTIVE ;Update the status line.
MOV DI,24*160+70
CALL WRITE_SCREEN
MOV AH,1 ;See if an ASCII character is
INT 16H ; available to be read.
JZ GET_KEY ;If not, see if Scroll Lock has
MOV AH,0 ; been toggled, else get the
INT 16H ; keystroke.
ESC: CMP AH,1 ;Is it Esc?
JNZ UP_ARROW
MOV DX,OFFSET DIR_FILE+1 ;If yes, make our temporary
MOV BYTE PTR[DIR_FILE+8],0 ; file, DIR.$$$, into a ASCIIZ
MOV AH,41H ; and delete it.
INT 21H
CALL CLS ;Clear the screen.
MOV CX,607H ;Turn the cursor back on
MOV AH,1
INT 10H
INT 20H ; and exit.
UP_ARROW: CMP AH,48H
JNZ DN_ARROW ;If UP ARROW, scroll down
MOV BP,-39 ; one line.
CALL SCROLL
DN_ARROW: CMP AH,50H
JNZ PG_UP ;If DOWN ARROW, scroll up
MOV BP,39 ; one line.
CALL SCROLL
PG_UP: CMP AH,49H
JNZ PG_DN ;If PgUp, scroll down
MOV BP,-39*20 ; 20 lines.
CALL SCROLL
PG_DN: CMP AH,51H
JNZ LF_ARROW ;If PgDn, scroll up
MOV BP,39*20 ; 20 lines.
CALL SCROLL
LF_ARROW: CMP AH,4BH
JNZ RT_ARROW ;If LEFT ARROW,
AND RIGHT,0 ; turn right off
OR LEFT,1 ; and left on.
RT_ARROW: CMP AH,4DH
JNZ NEXT_KEY ;If RIGHT ARROW,
AND LEFT,0 ; turn left off
OR RIGHT,1 ; and right on
NEXT_KEY: JMP GET_KEY
;---------------------------------------------------------------------;
; This subroutine will load COMMAND.COM/C DIR [directory] > DIR.$$$ ;
; On return, the file, DIR.$$$ will be opened, read and closed. ;
; The directory will be formated without CR's and LF's. Entry lines ;
; without a time will be padded with spaces. The directory parameter ;
; will be zeroed out, in preparation of the next directory parameter. ;
;---------------------------------------------------------------------;
WRITE_DIR: OR PARA_FLAG,1
MOV DX,OFFSET DOS_DIRECTIVE ;Set up the parameter
MOV BX,OFFSET ENVIRONMENT ; block for the load.
MOV WORD PTR COM_LINE_PTR+2,DS
PUSH DS ;When control is returned from
PUSH ES ; the load, all registers will
PUSH BP ; be changed, including SS and SP.
CLI
MOV CS:STACK_SEG,SS ;We, therefore, are responsible
MOV CS:STACK_PTR,SP ; for saving any registers whose
STI ; values are important to us.
MOV AX,4B00H
INT 21H ;Load COMMAND.COM/C
CLI
MOV SP,CS:STACK_PTR ;We are back in control.
MOV SS,CS:STACK_SEG ;Restore registers.
STI
POP BP
POP ES
POP DS
JNC OPEN_DIR ;If carry flag is set, COMMAND.COM
MOV DX,OFFSET ERROR_MSG ; was not found; inform the user
MOV AH,9
INT 21H
INT 20H ; and exit
OPEN_DIR: MOV BYTE PTR[DIR_FILE+8],0 ;else, open the file
MOV DX,OFFSET DIR_FILE+1 ; DIR.$$$
MOV AX,3D02H ; for reading.
INT 21H
READ_DIR: MOV BX,AX ;File handle in BX.
MOV DX,BUFFER_ADDR ;Point to our buffer.
MOV DI,DX ;Save destination.
ADD DX,1000 ;Leave room to format.
MOV SI,DX ;Start of file.
ADD SI,2 ;Bump past CR and LF.
MOV CX,30000 ;Attempt to read up to
MOV AH,3FH ; 30,000 bytes; that's
INT 21H ; half of our buffer.
ADD BUFFER_ADDR,30000 ;Adjust buffer for next read.
SUB AX,2 ;Adjust bytes read
MOV DX,AX ; and save.
CLOSE_DIR: MOV AH,3EH ;Close file.
INT 21H
MOV BYTE PTR[DIR_FILE+8],0DH
XOR BX,BX ;Zero in byte counter.
NEXT_LINE: MOV CX,39 ;39 byte lines.
GET_BYTE: LODSB ;Get a byte.
CMP AL,13 ;Is it carriage return?
JZ STORE_BLANK ;If yes, pad with spaces.
STOSB ;Else store the byte.
INC BX ;Increment byte counter.
LOOP GET_BYTE ;Get rest of line.
JMP SHORT CK_CR_LF ;Check for CR and LF.
STORE_BLANK: MOV AL,32 ;Pad the balance of the
REP STOSB ; line with spaces.
DEC SI
CK_CR_LF: CMP BYTE PTR [SI],13 ;Line end with CR?
JNZ CK_DIR_END ;If no, check if end of DIR.
ADD SI,2 ;Else, bump past CR and LF.
ADD BX,2 ;Adjust byte counter.
CK_DIR_END: CMP BX,DX ;Are we end of DIR?
JB NEXT_LINE ;If no, get next line.
MOV CX,800 ;Pad end of DIR with null
MOV AL,0 ; characters as end of DIR
REP STOSB ; signature.
ZERO_PATH: MOV CX,110 ;Zero out the directory
MOV DI,OFFSET DIR_PATH ; path in preparation
MOV AL,32 ; of the next parameter.
REP STOSB
RET ;And return.
;---------------------------------------------------;
; This subroutine will check to see if the left ;
; or right or both directories, should be scrolled. ;
; The boundaries of the directories will be checked ;
; in order to keep them on the screen. ;
;---------------------------------------------------;
SCROLL: CMP BYTE PTR ACTIVE,24 ;Is the left side active?
JNZ CK_RIGHT ;If no, check right side
MOV SI,CUR_OFFSET1 ; else, get current offset
ADD SI,BP ; add keyboard response.
CMP SI,DIR_OFFSET1 ;Is it below starting position?
JA UPPER_LIMIT1 ;If yes, check upper limit
MOV SI,DIR_OFFSET1 ; else set to starting position.
UPPER_LIMIT1: CMP BYTE PTR[SI],0 ;Is it one of the zero bytes at
JA OK1 ; we stored in the buffer?
MOV SI,DIR_OFFSET1 ;If yes, set to starting position
OK1: MOV CUR_OFFSET1,SI ; and the same with current.
MOV DI,480 ;Point to directory display line.
MOV AH,20 ;A count of 20 lines
CALL WRITE_LINE ; and display.
CK_RIGHT: CMP BYTE PTR ACTIVE+9,24
JNZ RETURN
MOV SI,CUR_OFFSET2 ;Do the same for the right side.
ADD SI,BP
CMP SI,DIR_OFFSET2
JA UPPER_LIMIT2
MOV SI,DIR_OFFSET2
UPPER_LIMIT2: CMP BYTE PTR[SI],0
JA OK2
MOV SI,DIR_OFFSET2
OK2: MOV CUR_OFFSET2,SI
MOV DI,562
MOV AH,20
CALL WRITE_LINE
RETURN: RET
;---------------------------------------------------;
; This subroutine will display the requested lines. ;
;---------------------------------------------------;
WRITE_LINE: CALL WRITE_SCREEN ;Display.
DEC AH
JNZ WRITE_LINE ;Do all lines.
RET ;Return.
;---------------------------------------------------------------;
; This subroutine displays the directory by writing directly ;
; to the screen buffer. To avoid screen noise (snow) on the ;
; color card, the horizontal retrace has to be monitored. ;
;---------------------------------------------------------------;
WRITE_SCREEN: MOV DX,STATUS_REG ;Get status register.
GET_LINE: MOV CX,39 ;Set count to 39 characters.
NEXT_BYTE: LODSB ;Get a byte.
MOV BL,AL ;Save it in BL.
HORZ_RET: IN AL,DX ;Get status.
TEST AL,1 ;Is it low?
JNZ HORZ_RET ;If not, wait until it is.
CLI ;No more interrupts.
WAIT: IN AL,DX ;Get status.
TEST AL,1 ;Is it high?
JZ WAIT ;If no, wait until it is.
MOV AL,BL ;Retrieve character; now it's OK
STOSB ; to write to screen buffer.
STI ;Interrupts back on.
INC DI ;Bump pointer past attribute.
LOOP NEXT_BYTE ;Get next byte.
ADD DI,82 ;Point to next line.
RET ;Return
;--------------------------------------------;
; This subroutine gets the current attribute ;
; and clears the screen with that attribute. ;
;--------------------------------------------;
CLS: XOR BH,BH ;Get current attribute
MOV AH,8 ; of display page zero.
INT 10H
MOV AL,25 ;Scroll all 25 lines.
MOV CX,0 ;From upper left
MOV DX,194FH ; to lower right.
MOV BH,AH ;Attribute to BH.
MOV AH,6
INT 10H
RET ;Return.
;----------------------------------------;
; This subroutine displays the messages. ;
;----------------------------------------;
DISP_STRING: MOV AH,9 ;Display a string.
INT 21H
RET ;Return.
;----------------------------------------------;
; 60,000 byte directory buffer at end of code.;
;----------------------------------------------;
BUFFER:
CODE ENDS
END START