home *** CD-ROM | disk | FTP | other *** search
- name shell
- page 55,132
- title 'Shell.asm -- simple MS-DOS shell'
-
- ;############################################################################
- ;
- ; 03-03-88 This code is based on the work of Ray Duncan in his
- ; book 'Advanced MS-DOS'- "The Microsoft guide for Assembly
- ; Language and C programmers." published by Microsoft Press -
- ; (C)1986 by Ray Duncan. The program SHELL.ASM is shown
- ; on pages 199 - 205.
- ;
- ; The code here is optimized for maximum speed of response and
- ; the missing END statement has been added.
- ;
- ; Mr. Duncan also presents a C version of this program
- ; on pages 195 - 198 along with an excellent discussion
- ; and explanation of the MS-DOS EXEC function.
- ;
- ; This code and/or the C version is an excellent start for
- ; building your own command interpreter. Items not recognized
- ; by SHELL are passed to the MS-DOS COMMAND.COM for internal
- ; or external processing.
- ;
- ; As presented here a very minimal amount of memory is used
- ; by the program. The C version would of course have a bigger
- ; .EXE file and probably be slower.
- ;
- ; L. B. Neal
- ; Sunnyvale, CA
- ; March 3, 1988
- ; PYSMATIC BBS 408-992-0372
-
- ;#############################################################################
-
- STDIN EQU 0
- STDOUT EQU 1
- STDERR EQU 2
-
- CR EQU 0DH
- LF EQU 0AH
- BLANK EQU 20H
- ESC_S EQU 01BH
-
- ;--------------------------------------------
- ;
- CSEG SEGMENT PARA PUBLIC 'CODE'
- ASSUME CS:CSEG,DS:DATA,SS:STACK
-
- SHELL PROC FAR
- MOV AX,DATA
- MOV DS,AX
- MOV AX,ES:[002CH]
- MOV ENV_SEG,AX
- MOV BX,100H
- MOV AH,04AH
- INT 21H
- JNC SHELL1
- MOV DX,OFFSET MSG1
- MOV CX,MSG1_LENGTH
- JMP SHELL4
-
- SHELL1: CALL GET_COMSPEC ; Get the COMSPEC
- JNC SHELL2
- MOV DX,OFFSET MSG3
- MOV CX,MSG3_LENGTH
- JMP SHELL4
-
- SHELL2: MOV DX,OFFSET SHELL3 ; Set CNTR-C vector
- MOV AX,CS
- MOV DS,AX
- MOV AX,2523H
- INT 21H
- MOV AX,DATA
- MOV DS,AX
- MOV ES,AX
-
- ;-------------------------------------------------------------
- ; This is the main wait for input processing loop in the SHELL mode.
- ;
-
- SHELL3: MOV DX,OFFSET PROMPT ; Get_cmd inline coded
- MOV CX,PROMPT_LENGTH
- MOV BX,STDOUT ; Write prompt to screen
- MOV AH,40H
- INT 21H
- MOV DX,OFFSET INP_BUF
- MOV CX,INP_BUF_LENGTH
- MOV BX,STDIN ; Read the keyboard
- MOV AH,3FH
- INT 21H
- MOV SI,OFFSET INP_BUF
- MOV CX,INP_BUF_LENGTH
- CMP BYTE PTR [SI],0DH ; Skip rest if CR
- JNE GCMD1 ; This gives much faster response
- JMP SHORT SHELL1
-
- ;------------------------------------------------------------------------
- ; Here the command line is processed if was not just a CR
- ;
-
- GCMD1: CMP BYTE PTR [SI],'a'
- JAE CK_ALF
- JMP SHORT GCMD2
- CK_ALF: CMP BYTE PTR [SI],'z'
- JBE UPCASE
- JMP GCMD2
- UPCASE: SUB BYTE PTR [SI],'a'-'A'
- GCMD2: INC SI
- LOOP GCMD1
-
- MOV SI,OFFSET COMMANDS
- INTR1: CMP BYTE PTR [SI],0
- JE INTR7
- MOV DI,OFFSET INP_BUF
- INTR2: CMP BYTE PTR [DI],BLANK
- JNE INTR3
- INC DI
- JMP INTR2
- INTR3: MOV AL,[SI]
- OR AL,AL
- JZ INTR4
- CMP AL,[DI]
- JNZ INTR6
- INC SI
- INC DI
- JMP INTR3
- INTR4: CMP BYTE PTR [DI],CR
- JE INTR5
- CMP BYTE PTR [DI],BLANK
- JNE INTR6
- INTR5: CALL WORD PTR [SI+1]
- CLC
- JMP READ ; Read CMD line again
- INTR6: LODSB
- OR AL,AL
- JNZ INTR6
- ADD SI,2
- JMP INTR1
- INTR7: STC
-
- READ: JNC SHELL3 ; Loop on cmd line again
- CALL EXTRINSIC ; Send external command to Comamnd.com
- JMP SHELL3
-
- SHELL4: MOV BX,STDERR
- MOV AH,40H
- INT 21H
- MOV AX,4C01H
- INT 21H
-
- SHELL ENDP
-
- STK_SEG DW 0
- STK_PTR DW 0
-
- ;----------------------------------------------------
- ; Here we pass the command line to COMMAND.COM when
- ; SHELL.EXE can't handle the string.
- ;
-
- EXTRINSIC PROC NEAR
- MOV AL,CR
- MOV CX,CMD_TAIL_LENGTH
- MOV DI,OFFSET CMD_TAIL+1
- CLD
- REPNZ SCASB
- MOV AX,DI
- SUB AX,OFFSET CMD_TAIL+2
- MOV CMD_TAIL,AL
- MOV PAR_CMD,OFFSET CMD_TAIL
- CALL EXEC
- RET
- EXTRINSIC ENDP
-
- ;------------------------------------------------------
- ; This proceedure gets the comspec
- ;
-
- GET_COMSPEC PROC NEAR
- MOV SI,OFFSET COM_VAR
- CALL GET_ENV
- JC GCSP2
- MOV SI,OFFSET COM_SPEC
- GCSP1: MOV AL,ES:[DI]
- MOV [SI],AL
- INC SI
- INC DI
- OR AL,AL
- JNZ GCSP1
- GCSP2: RET
- GET_COMSPEC ENDP
-
- ;-----------------------------------------------
- ; Get the environment information
- ;
-
- GET_ENV PROC NEAR
- MOV ES,ENV_SEG
- XOR DI,DI
- GENV1: MOV BX,SI
- CMP BYTE PTR ES:[DI],0
- JNE GENV2
- STC
- RET
- GENV2: MOV AL,[BX]
- OR AL,AL
- JZ GENV3
- CMP AL,ES:[DI]
- JNE GENV4
- INC BX
- INC DI
- JMP GENV2
- GENV3: RET
- GENV4: XOR AL,AL
- MOV CX,-1
- CLD
- REPNZ SCASB
- JMP GENV1
- GET_ENV ENDP
-
- ;--------------------------------------------------
- ; Here we call MS-DOS EXEC function to run COMMAND.COM.
- ;
-
- EXEC PROC NEAR
- PUSH DS
- PUSH ES
- MOV CS:STK_SEG,SS
- MOV CS:STK_PTR,SP
- MOV DX,OFFSET COM_SPEC
- MOV BX,OFFSET PAR_BLK
- MOV AH,04BH
- MOV AL,0
- INT 21H
- MOV SS,CS:STK_SEG
- MOV SP,CS:STK_PTR
- POP ES
- POP DS
- JNC EXEC1
- MOV DX,OFFSET MSG2
- MOV CX,MSG2_LENGTH
- MOV BX,STDERR
- MOV AH,040H
- INT 21H
- EXEC1: RET
- EXEC ENDP
-
- ;---------------------------------------------------------
- ; A simple ANSI.SYS internal command to clear the screen.
- ;
-
- CLS_CMD PROC NEAR
- MOV DX,OFFSET CLS_STR
- MOV CX,CLS_STR_LENGTH
- MOV BX,STDOUT
- MOV AH,040H
- INT 21H
- RET
- CLS_CMD ENDP
-
- ;---------------------------------------------------------
- ; Internal command to run COMMAND.COM
- ;
-
- DOS_CMD PROC NEAR
- MOV PAR_CMD,OFFSET NULTAIL
- CALL EXEC
- RET
- DOS_CMD ENDP
-
- ;--------------------------------------------------------
- ; Internal command to leave SHELL.EXE.
- ;
-
- EXIT_CMD PROC NEAR
- MOV AX,04C00H
- INT 21H
- EXIT_CMD ENDP
-
- CSEG ENDS
-
- ;--------------------------------------------
-
- STACK SEGMENT PARA STACK 'STACK'
- DW 64 DUP(?)
- STACK ENDS
-
- ;---------------------------------------------
-
- DATA SEGMENT PARA PUBLIC 'DATA'
-
- COMMANDS EQU $ ; The sample command table for
- DB 'CLS',0 ; this command interpreter
- DW CLS_CMD
- DB 'DOS',0
- DW DOS_CMD
- DB 'EXIT',0
- DW EXIT_CMD
- DB 0
-
- COM_VAR DB 'COMSPEC=',0
- COM_SPEC DB 80 DUP(0)
- NULTAIL DB 0,CR
- CMD_TAIL DB 0,' /C '
-
- INP_BUF DB 80 DUP(0)
- INP_BUF_LENGTH EQU $-INP_BUF
- CMD_TAIL_LENGTH EQU $-CMD_TAIL-1
-
- ;-----------------------------------------------------------
- ; The definition of SHELL.EXE's prompt.
- ;
-
- PROMPT DB CR,'SHELL:> '
- PROMPT_LENGTH EQU $-PROMPT
-
-
-
- ENV_SEG DW 0
-
-
- ;-----------------------------------------------------------
- ; Internal messages for SHELL.EXE errors
- ;
-
- MSG1 DB CR,LF
- DB 'Unable to de-allocate memory.'
- DB CR,LF
- MSG1_LENGTH EQU $-MSG1
-
- MSG2 DB CR,LF
- DB 'EXEC of COMMAND.COM failed.'
- DB CR,LF
- MSG2_LENGTH EQU $-MSG2
-
- MSG3 DB CR,LF
- DB 'No COMSPEC variable in Environment.'
- DB CR,LF
- MSG3_LENGTH EQU $-MSG3
-
-
-
- CLS_STR DB ESC_S,'[2J' ; ANSI.SYS clear screen string.
- CLS_STR_LENGTH EQU $-CLS_STR
-
- PAR_BLK EQU $
- DW 0
- PAR_CMD DW OFFSET CMD_TAIL
- DW SEG CMD_TAIL
- DD -1
- DD -1
-
- DATA ENDS
- END SHELL
- END