home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / assemblr / library / shellasm / shell.asm < prev    next >
Assembly Source File  |  1988-03-03  |  7KB  |  356 lines

  1. name  shell
  2. page  55,132
  3. title 'Shell.asm -- simple MS-DOS shell'
  4.  
  5. ;############################################################################
  6. ;
  7. ;  03-03-88  This code is based on the work of Ray Duncan in his
  8. ;            book 'Advanced MS-DOS'- "The Microsoft guide for Assembly
  9. ;            Language and C programmers." published by Microsoft Press -
  10. ;            (C)1986 by Ray Duncan.  The program SHELL.ASM is shown
  11. ;            on pages 199 - 205.  
  12. ;
  13. ;            The code here is optimized for maximum speed of response and
  14. ;            the missing END statement has been added.  
  15. ;
  16. ;            Mr. Duncan also presents a C version of this program
  17. ;            on pages 195 - 198 along with an excellent discussion
  18. ;            and explanation of the MS-DOS EXEC function.
  19. ;
  20. ;            This code and/or the C version is an excellent start for
  21. ;            building your own command interpreter.  Items not recognized
  22. ;            by SHELL are passed to the MS-DOS COMMAND.COM for internal
  23. ;            or external processing.
  24. ;
  25. ;            As presented here a very minimal amount of memory is used
  26. ;            by the program.  The C version would of course have a bigger
  27. ;            .EXE file and probably be slower. 
  28. ;
  29. ;                                     L. B. Neal
  30. ;                                     Sunnyvale, CA
  31. ;                                     March 3, 1988
  32. ;                                     PYSMATIC BBS 408-992-0372
  33.  
  34. ;#############################################################################
  35.  
  36. STDIN    EQU    0
  37. STDOUT    EQU    1
  38. STDERR    EQU    2
  39.  
  40. CR    EQU    0DH
  41. LF    EQU    0AH
  42. BLANK    EQU    20H
  43. ESC_S    EQU    01BH
  44.  
  45. ;--------------------------------------------
  46. ;
  47. CSEG    SEGMENT    PARA PUBLIC 'CODE'
  48.     ASSUME    CS:CSEG,DS:DATA,SS:STACK
  49.  
  50. SHELL    PROC    FAR
  51.     MOV    AX,DATA
  52.     MOV    DS,AX
  53.     MOV    AX,ES:[002CH]
  54.     MOV    ENV_SEG,AX
  55.     MOV    BX,100H
  56.     MOV    AH,04AH
  57.     INT    21H
  58.     JNC    SHELL1
  59.     MOV    DX,OFFSET MSG1
  60.     MOV    CX,MSG1_LENGTH
  61.     JMP    SHELL4
  62.  
  63. SHELL1: CALL    GET_COMSPEC        ; Get the COMSPEC
  64.     JNC    SHELL2
  65.     MOV    DX,OFFSET MSG3
  66.     MOV    CX,MSG3_LENGTH
  67.     JMP    SHELL4
  68.  
  69. SHELL2:    MOV    DX,OFFSET SHELL3    ; Set CNTR-C vector
  70.     MOV    AX,CS
  71.     MOV    DS,AX
  72.     MOV    AX,2523H
  73.     INT    21H
  74.     MOV    AX,DATA
  75.     MOV    DS,AX
  76.     MOV    ES,AX
  77.  
  78. ;-------------------------------------------------------------
  79. ;  This is the main wait for input processing loop in the SHELL mode.  
  80. ;
  81.  
  82. SHELL3:    MOV    DX,OFFSET PROMPT    ; Get_cmd inline coded
  83.     MOV    CX,PROMPT_LENGTH
  84.     MOV    BX,STDOUT        ; Write prompt to screen
  85.     MOV    AH,40H
  86.     INT    21H
  87.     MOV    DX,OFFSET INP_BUF
  88.     MOV    CX,INP_BUF_LENGTH
  89.     MOV    BX,STDIN        ; Read the keyboard
  90.     MOV    AH,3FH
  91.     INT    21H
  92.     MOV    SI,OFFSET INP_BUF
  93.     MOV    CX,INP_BUF_LENGTH
  94.     CMP    BYTE PTR [SI],0DH    ; Skip rest if CR
  95.     JNE    GCMD1            ; This gives much faster response
  96.     JMP    SHORT SHELL1
  97.  
  98. ;------------------------------------------------------------------------
  99. ;  Here the command line is processed if was not just a CR
  100. ;
  101.  
  102. GCMD1:    CMP    BYTE PTR [SI],'a'
  103.     JAE    CK_ALF
  104.     JMP     SHORT GCMD2
  105. CK_ALF:    CMP    BYTE PTR [SI],'z'
  106.     JBE    UPCASE
  107.     JMP    GCMD2
  108. UPCASE:    SUB    BYTE PTR [SI],'a'-'A'
  109. GCMD2:    INC    SI
  110.     LOOP    GCMD1
  111.  
  112.     MOV    SI,OFFSET COMMANDS
  113. INTR1:    CMP    BYTE PTR [SI],0
  114.     JE    INTR7
  115.     MOV    DI,OFFSET INP_BUF
  116. INTR2:    CMP    BYTE PTR [DI],BLANK
  117.     JNE    INTR3
  118.     INC    DI
  119.     JMP    INTR2
  120. INTR3:  MOV    AL,[SI]
  121.     OR    AL,AL
  122.     JZ    INTR4
  123.     CMP    AL,[DI]
  124.     JNZ    INTR6
  125.     INC    SI
  126.     INC    DI
  127.     JMP    INTR3
  128. INTR4:    CMP    BYTE PTR [DI],CR
  129.     JE    INTR5
  130.     CMP    BYTE PTR [DI],BLANK
  131.     JNE    INTR6
  132. INTR5:    CALL    WORD PTR [SI+1]
  133.     CLC    
  134.     JMP    READ            ; Read CMD line again
  135. INTR6:    LODSB
  136.     OR    AL,AL
  137.     JNZ    INTR6
  138.     ADD    SI,2
  139.     JMP    INTR1
  140. INTR7:    STC
  141.     
  142. READ:    JNC    SHELL3            ; Loop on cmd line again
  143.     CALL    EXTRINSIC        ; Send external command to Comamnd.com
  144.     JMP    SHELL3
  145.  
  146. SHELL4: MOV    BX,STDERR
  147.     MOV    AH,40H
  148.     INT    21H
  149.     MOV    AX,4C01H
  150.     INT    21H
  151.  
  152. SHELL    ENDP
  153.  
  154. STK_SEG    DW    0
  155. STK_PTR    DW    0
  156.  
  157. ;----------------------------------------------------
  158. ; Here we pass the command line to COMMAND.COM when
  159. ; SHELL.EXE can't handle the string.
  160. ;
  161.  
  162. EXTRINSIC PROC    NEAR
  163.     MOV    AL,CR
  164.     MOV    CX,CMD_TAIL_LENGTH
  165.     MOV    DI,OFFSET CMD_TAIL+1
  166.     CLD
  167.     REPNZ    SCASB
  168.     MOV    AX,DI
  169.     SUB    AX,OFFSET CMD_TAIL+2
  170.     MOV    CMD_TAIL,AL
  171.     MOV    PAR_CMD,OFFSET CMD_TAIL
  172.     CALL    EXEC
  173.     RET
  174. EXTRINSIC  ENDP
  175.  
  176. ;------------------------------------------------------
  177. ;  This proceedure gets the comspec
  178. ;
  179.  
  180. GET_COMSPEC PROC NEAR
  181.     MOV    SI,OFFSET COM_VAR
  182.     CALL    GET_ENV
  183.     JC    GCSP2
  184.     MOV    SI,OFFSET COM_SPEC
  185. GCSP1:    MOV    AL,ES:[DI]
  186.     MOV    [SI],AL
  187.     INC    SI
  188.     INC    DI
  189.     OR    AL,AL
  190.     JNZ    GCSP1
  191. GCSP2:    RET
  192. GET_COMSPEC ENDP
  193.  
  194. ;-----------------------------------------------
  195. ;  Get the environment information
  196. ;
  197.  
  198. GET_ENV    PROC    NEAR
  199.     MOV    ES,ENV_SEG
  200.     XOR    DI,DI
  201. GENV1:    MOV    BX,SI
  202.     CMP    BYTE PTR ES:[DI],0
  203.     JNE    GENV2
  204.     STC
  205.     RET
  206. GENV2:    MOV    AL,[BX]
  207.     OR    AL,AL
  208.     JZ    GENV3
  209.     CMP    AL,ES:[DI]
  210.     JNE    GENV4
  211.     INC    BX
  212.     INC    DI
  213.     JMP    GENV2
  214. GENV3:    RET
  215. GENV4:    XOR    AL,AL
  216.     MOV    CX,-1
  217.     CLD
  218.     REPNZ    SCASB
  219.     JMP    GENV1
  220. GET_ENV ENDP
  221.  
  222. ;--------------------------------------------------
  223. ; Here we call MS-DOS EXEC function to run COMMAND.COM.
  224. ;
  225.  
  226. EXEC    PROC    NEAR
  227.     PUSH    DS
  228.     PUSH    ES
  229.     MOV    CS:STK_SEG,SS
  230.     MOV    CS:STK_PTR,SP
  231.     MOV    DX,OFFSET COM_SPEC
  232.     MOV    BX,OFFSET PAR_BLK
  233.     MOV    AH,04BH
  234.     MOV    AL,0
  235.     INT    21H
  236.     MOV    SS,CS:STK_SEG
  237.     MOV    SP,CS:STK_PTR
  238.     POP    ES
  239.     POP    DS
  240.     JNC    EXEC1
  241.     MOV    DX,OFFSET MSG2
  242.     MOV    CX,MSG2_LENGTH
  243.     MOV    BX,STDERR
  244.     MOV    AH,040H
  245.     INT    21H
  246. EXEC1:    RET
  247. EXEC    ENDP
  248.  
  249. ;---------------------------------------------------------
  250. ; A simple ANSI.SYS internal command to clear the screen.
  251. ;
  252.  
  253. CLS_CMD    PROC    NEAR
  254.     MOV    DX,OFFSET CLS_STR
  255.     MOV    CX,CLS_STR_LENGTH
  256.     MOV    BX,STDOUT
  257.     MOV    AH,040H
  258.     INT    21H
  259.     RET
  260. CLS_CMD    ENDP
  261.  
  262. ;---------------------------------------------------------
  263. ;  Internal command to run COMMAND.COM
  264. ;
  265.  
  266. DOS_CMD    PROC    NEAR
  267.     MOV    PAR_CMD,OFFSET NULTAIL
  268.     CALL    EXEC
  269.     RET
  270. DOS_CMD    ENDP
  271.  
  272. ;--------------------------------------------------------
  273. ; Internal command to leave SHELL.EXE.
  274. ;
  275.  
  276. EXIT_CMD PROC    NEAR
  277.     MOV    AX,04C00H
  278.     INT    21H
  279. EXIT_CMD  ENDP
  280.  
  281. CSEG    ENDS
  282.  
  283. ;--------------------------------------------
  284.  
  285. STACK    SEGMENT  PARA STACK 'STACK'
  286.     DW    64 DUP(?)
  287. STACK    ENDS
  288.  
  289. ;---------------------------------------------
  290.  
  291. DATA    SEGMENT PARA PUBLIC 'DATA'
  292.  
  293. COMMANDS EQU $                ; The sample command table for
  294.     DB    'CLS',0            ; this command interpreter
  295.     DW    CLS_CMD
  296.     DB    'DOS',0
  297.     DW    DOS_CMD
  298.     DB    'EXIT',0
  299.     DW    EXIT_CMD
  300.     DB    0
  301.  
  302. COM_VAR    DB    'COMSPEC=',0
  303. COM_SPEC DB    80 DUP(0)
  304. NULTAIL    DB    0,CR
  305. CMD_TAIL DB    0,' /C '
  306.  
  307. INP_BUF    DB    80 DUP(0)
  308. INP_BUF_LENGTH EQU $-INP_BUF
  309. CMD_TAIL_LENGTH EQU $-CMD_TAIL-1
  310.  
  311. ;-----------------------------------------------------------
  312. ; The definition of SHELL.EXE's prompt.
  313. ;
  314.  
  315. PROMPT    DB    CR,'SHELL:> '
  316. PROMPT_LENGTH EQU $-PROMPT
  317.  
  318.  
  319.  
  320. ENV_SEG    DW    0
  321.  
  322.  
  323. ;-----------------------------------------------------------
  324. ; Internal messages for SHELL.EXE errors
  325. ;
  326.  
  327. MSG1    DB    CR,LF
  328.     DB    'Unable to de-allocate memory.'
  329.     DB    CR,LF
  330. MSG1_LENGTH EQU $-MSG1
  331.  
  332. MSG2    DB    CR,LF
  333.     DB    'EXEC of COMMAND.COM failed.'
  334.     DB    CR,LF
  335. MSG2_LENGTH EQU $-MSG2
  336.  
  337. MSG3    DB    CR,LF
  338.     DB    'No COMSPEC variable in Environment.'
  339.     DB    CR,LF
  340. MSG3_LENGTH EQU $-MSG3
  341.  
  342.  
  343.  
  344. CLS_STR    DB    ESC_S,'[2J'        ; ANSI.SYS clear screen string.
  345. CLS_STR_LENGTH    EQU $-CLS_STR
  346.  
  347. PAR_BLK EQU    $
  348.     DW    0
  349. PAR_CMD    DW    OFFSET CMD_TAIL
  350.     DW    SEG CMD_TAIL
  351.     DD    -1
  352.     DD    -1
  353.  
  354. DATA    ENDS
  355.     END    SHELL
  356.     END