home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 10 / 10.iso / l / l440 / 2.ddi / CHAP7 / MON.ASM < prev    next >
Encoding:
Assembly Source File  |  1990-09-27  |  8.9 KB  |  417 lines

  1.     page    78,132
  2.     title    Monitor for IBM PC by Tim Paterson
  3.  
  4.     include    dos.inc
  5.  
  6. ;System equates
  7.  
  8. BreakVect    =    1BH
  9. TermAddr    equ    word ptr 0AH
  10. PROMPT        =    ">"
  11.  
  12. ExecBlock    struc
  13.  
  14. Environment    dw    0        ;Pass on parent's environment
  15. CommandTail    dw    80H
  16. CommandTailSeg    dw    0
  17. FCB1        dw    5CH
  18. FCB1Seg        dw    0
  19. FCB2        dw    6CH
  20. FCB2Seg        dw    0
  21. InitSp        dw    0
  22. InitSs        dw    0
  23. InitIp        dw    0
  24. InitCs        dw    0
  25.  
  26. ExecBlock    ends
  27.  
  28.     .model    small
  29.     .code
  30.     .data
  31. Strings    segment    byte public
  32. Strings    ends
  33. InitSeg segment public
  34. InitSeg ends
  35. LastSeg    segment byte
  36.     ret                ;End of init code
  37. LastSeg    ends
  38.  
  39. DGroup    group    _TEXT,_DATA,Strings,InitSeg,LastSeg
  40.  
  41.     .data
  42.  
  43.     public    AxSave,BxSave,SpSave,SsSave,DsSave,CsSave,IpSave,FlSave
  44.     public    BpSave,SiSave,DiSave,TestPSP
  45.  
  46.     extrn    LineBuf:byte, TCount:word
  47.  
  48. ExecFile    ExecBlock<,DGroup:LineBuf>
  49. TestPSP        dw    0
  50. NextInt15    dd    0
  51.  
  52.     ALIGN    2
  53.     dw    80H dup(?)        ;Working stack area
  54. STACK    label    word
  55. ;Register save area
  56. AxSave    dw    ?
  57. BxSave    dw    ?
  58. CxSave    dw    ?
  59. DxSave    dw    ?
  60. SpSave    dw    ?
  61. BpSave    dw    ?
  62. SiSave    dw    ?
  63. DiSave    dw    ?
  64. DsSave    dw    ?
  65. EsSave    dw    ?
  66. SsSave    dw    ?
  67. CsSave    dw    ?
  68. IpSave    dw    ?
  69. FlSave    dw    ?
  70.  
  71. ;Start of Monitor code
  72.  
  73.     .code
  74.     assume    cs:DGroup,ds:DGroup,es:DGroup,ss:DGroup
  75.  
  76.     public    Monitor, Command, Error, PrintAbort, PErr, ErrMes
  77.  
  78.     extrn    InBuf:near, OutCh:near, CrLf:near, PrintMes:near, ScanB:near
  79.     extrn    Tab:near, ReEnter:near
  80.  
  81.     org    100H
  82.  
  83. Monitor:
  84.          cld
  85.  
  86.     IFDEF    DEBUG
  87. ;Copy psp
  88.     xor    si,si
  89.     mov    di,si
  90.     push    cs
  91.     pop    es
  92.     mov    cx,100H/2
  93. rep    movsw
  94.     push    cs
  95.     pop    ds
  96.     push    cs
  97.     pop    ss
  98.     ENDIF    ;DEBUG
  99.  
  100.     mov    sp,offset DGroup:Stack
  101.     DOS    Version,0
  102.     cmp    al,3            ;Version OK?
  103.     jae    VersionOK
  104. ;Bad version.  Terminate in a DOS 1.0-compatible way
  105.     DOS    Print,,<offset DGroup:BadVersionMsg>
  106.     int    20H
  107.  
  108. VersionOK:
  109.     call    Init
  110.     mov    si,offset DGroup:Header
  111.     call    PrintMes
  112. ;Load file for debugging
  113.     mov    ax,cs
  114.  
  115.     IFDEF    DEBUG
  116.     sub    ax,10H            ;Get to true PSP
  117.     mov    es,ax
  118.     ENDIF    ;DEBUG
  119.  
  120.     mov    bx,[CsSave]        ;First segment to free
  121.     sub    bx,ax            ;Compute paragraphs we're keeping
  122.     DOS    ResizeMem
  123.  
  124.     IFDEF    DEBUG
  125.     push    cs
  126.     pop    es
  127.     ENDIF    ;DEBUG
  128.  
  129.     mov    si,80H            ;Point to command line in PSP
  130.     lodsb                ;Get length byte
  131.     cbw
  132.     xchg    cx,ax            ;Put length in cx
  133.     call    ParseFile
  134.     mov    si,dx
  135.     cmp    byte ptr [si],0        ;Was there a file name?
  136.     jz    Command
  137.     mov    [AxSave],ax
  138.     mov    [ExecFile].CommandTailSeg,ds
  139.     mov    [ExecFile].FCB1Seg,ds
  140.     mov    [ExecFile].FCB2Seg,ds
  141.     mov    bx,offset DGroup:ExecFile
  142.     DOS    Exec,1            ;Load, don't execute
  143.     jc    NoFileLoad
  144.     mov    ax,[ExecFile].InitIp
  145.     mov    [IpSave],ax
  146.     mov    ax,[ExecFile].InitCs
  147.     mov    [CsSave],ax
  148.     mov    ax,[ExecFile].InitSp
  149.     mov    [SpSave],ax
  150.     mov    ax,[ExecFile].InitSs
  151.     mov    [SsSave],ax
  152.     DOS    GetPSP
  153.     mov    [DsSave],bx        ;DS = ES = PSP
  154.     mov    [EsSave],bx
  155.     mov    es,bx
  156.     mov    es:[TermAddr],offset DGroup:ProgTerminate
  157.     mov    es:[TermAddr+2],cs    ;Terminate address now set
  158.     mov    [TestPSP],bx
  159.     mov    bx,cs
  160.  
  161.     IFDEF    DEBUG
  162.     sub    bx,10H            ;True PSP
  163.     ENDIF    ;DEBUG
  164.  
  165.     DOS    SetPSP            ;Change back to our own PSP
  166. Command:
  167. ;Re-establish initial conditions
  168.     cld
  169.     mov    ax,cs
  170.     mov    ds,ax
  171.     mov    es,ax
  172.     mov    ss,ax
  173.     mov    sp,offset DGroup:STACK
  174.     sti
  175.     MOV    AL,PROMPT
  176.     CALL    OutCh
  177.     CALL    INBUF        ;Get command line
  178. ;From now and throughout command line processing, SI points
  179. ;to next character in command line to be processed.
  180.     CALL    SCANB        ;Scan off leading blanks
  181.     JZ    COMMAND        ;Null command?
  182.     LODSB            ;AL=first non-blank character
  183. ;Prepare command letter for table lookup
  184.     SUB    AL,"B"        ;Low end range check
  185.     JC    ERR1
  186.     CMP    AL,"U"+1-"B"    ;Upper end range check
  187.     JNC    ERR1
  188.     SHL    AL,1        ;Times two
  189.     CBW            ;Now a 16-bit quantity
  190.     XCHG    BX,AX        ;In BX we can address with it
  191.     CALL    [BX+COMTAB]    ;Execute command
  192.     jmp    Command        ;Get next command
  193.  
  194. NoFileLoad:
  195.     mov    si,offset DGroup:FileErrMsg
  196.     jmp    PrintAbort
  197.  
  198. ERR1:    JMP    PERR
  199.  
  200. BadVersionMsg    db    "Invalid DOS--version 3 or later required$"
  201. Header        db    13,10,"IBM-PC Monitor 1.0",13,10+80H
  202. SYNERR        db    '^'
  203. ERRMES        db    " Error",13,10+80H
  204. ProgEndMsg    db    13,10,"Program terminated",13,10+80H
  205. FileErrMsg    db    "Error loading file",13,10+80H
  206.  
  207. ;Ctrl-BREAK handler.  Allows program abort.
  208. Interrupt:
  209.     MOV    AL,20H        ;End of interrupt command
  210.     OUT    20H,al        ;Send to 8259A
  211.     mov    al,0AEH        ;Enable keyboard
  212.     out    64H,al        ;Send to keyboard
  213.     MOV    AL,"^"
  214.     CALL    OutCh
  215.     MOV    AL,"C"
  216.     CALL    OutCh
  217.     call    CRLF
  218.     jmp    Command
  219.  
  220. SysReq:
  221.     cmp    ax,8500H        ;Sys Req key pressed?
  222.     jnz    ChainInt15
  223.     mov    cs:[TCount],1        ;Stop step mode
  224.     jmp    ReEnter
  225.  
  226. ChainInt15:
  227.     jmp    cs:[NextInt15]
  228.  
  229. ;Command Table. Command letter indexes into table to get
  230. ;address of command. PERR prints error for no such command.
  231.  
  232. DwExt    Macro    lab
  233.     extrn    lab:near
  234.     dw    offset DGroup:lab
  235.     EndM
  236.  
  237. COMTAB    label    word
  238.     DW    PERR        ;B
  239.     DwExt    COMPARE        ;C
  240.     DwExt    DUMP        ;D
  241.     DwExt    ENTER        ;E
  242.     DwExt    FILL        ;F
  243.     DwExt    GO        ;G
  244.     DW    PERR        ;H
  245.     DwExt    INPUT        ;I
  246.     DW    PERR        ;J
  247.     DW    PERR        ;K
  248.     DW    PERR        ;L
  249.     DwExt    MOVE        ;M
  250.     DW    PERR        ;N
  251.     DwExt    OUTPUT        ;O
  252.     DW    PERR        ;P
  253.     DW    Quit        ;Q
  254.     DwExt    REG        ;R
  255.     DwExt    SEARCH        ;S
  256.     DwExt    TRACE        ;T
  257.     DwExt    UnAssemble    ;U
  258.  
  259. ParseFile:
  260. ;Find start and end of file name
  261. ;Inputs:
  262. ;    ds:si = pointer to input string
  263. ;    cx = length of string
  264. ;Outputs:
  265. ;    ax = Starting value for ax (drive validity flags)
  266. ;    dx = File name to execute, zero-terminated
  267.  
  268.     mov    bx,si            ;Save initial pointer
  269.     call    ScanB
  270.     mov    dx,si            ;Save starting address
  271.     call    FindNameEnd
  272.     sub    bx,si
  273.     neg    bx            ;Amount scanned so far
  274.     sub    cx,bx            ;Amount remaining in string
  275.     mov    bx,si            ;Save end of name--start of args
  276.     mov    di,offset DGroup:LineBuf+1
  277.     mov    [di-1],cl        ;Put length in first byte
  278.     inc    cx            ;Copy terminating CR
  279. rep    movsb                ;Copy to argument buffer
  280.     mov    si,bx            ;Restore start of args
  281.     mov    di,5CH            ;First FCB
  282.     DOS    ParseName,1        ;Parse file name, scan off blanks
  283.     cbw                ;0FFH if invalid drive
  284.     and    al,ah            ;Make sure al is zero or one
  285.     xchg    cx,ax            ;Save return value in cl
  286.     call    FindNameEnd        ;Skip over any "\" chars
  287.     mov    di,6CH            ;Second FCB
  288.     DOS    ParseName,1        ;Parse file name, scan off blanks
  289.     cbw                ;0FFH if invalid drive
  290.     and    ah,al            ;Make sure ah is zero or one
  291.     mov    al,cl
  292.     mov    byte ptr [bx],0        ;Zero terminate file name
  293.     ret
  294.  
  295. FindNameEnd:
  296.     lodsb
  297.     cmp    al," "            ;Check for blank or control char
  298.     jbe    NameEnd
  299.     cmp    al,","
  300.     jz    NameEnd
  301.     cmp    al,";"
  302.     jz    NameEnd
  303.     cmp    al,"/"
  304.     jnz    FindNameEnd
  305. NameEnd:
  306.     dec    si            ;Point back at terminator
  307.     ret
  308.  
  309.  
  310. ;Command error. SI has been incremented beyond the
  311. ;command letter so it must decremented for the
  312. ;error pointer to work.
  313.  
  314. PERR:
  315.     DEC    SI
  316.  
  317. ;Syntax error. SI points to character in the input buffer
  318. ;which caused error. By subtracting from start of buffer,
  319. ;we will know how far to tab over to appear directly below
  320. ;it on the terminal. Then print "^ Error".
  321.  
  322. ERROR:
  323.     SUB    SI,offset DGroup:LINEBUF-1    ;How many char processed so far?
  324.     MOV    CX,SI        ;Parameter for TAB in CX
  325.     CALL    TAB        ;Directly below bad char
  326.     MOV    SI,offset DGroup:SYNERR    ;Error message
  327.  
  328. ;Print error message and abort to command level
  329.  
  330. PrintAbort:
  331.     CALL    PRINTMES
  332.     JMP    COMMAND
  333.  
  334. ;************************************************************
  335. ; "Q" - Quit
  336.  
  337. ProgTerminate:
  338. ;TestPSP = our own PSP if we are terminating the child in order to quit
  339. ;Monitor (suppress "program terminated" message).
  340.     push    cs
  341.     pop    ds
  342.     mov    bx,cs
  343.  
  344.     IFDEF    DEBUG
  345.     sub    bx,10H            ;True PSP
  346.     ENDIF    ;DEBUG
  347.  
  348.     mov    ax,bx
  349.     xchg    bx,[TestPSP]        ;Set to our own PSP to show no child
  350.     cmp    ax,bx            ;Do we have a child?
  351.     jz    JustExit
  352.     mov    si,offset DGroup:ProgEndMsg
  353.     jmp    PrintAbort        ;Print message, get next command line
  354.  
  355. Quit:
  356. ;We must end child first.  If no child, TestPSP = our own PSP, so we'll
  357. ;just terminate directly.  If there is a child, set TestPSP to our own PSP
  358. ;as a flag to ProgTerminate to suppress "program terminated" message.
  359.     mov    bx,cs
  360.  
  361.     IFDEF    DEBUG
  362.     sub    bx,10H            ;True PSP
  363.     ENDIF    ;DEBUG
  364.  
  365.     xchg    bx,[TestPSP]
  366.     DOS    SetPSP
  367. JustExit:
  368.     lds    dx,[NextInt15]
  369.     DOS    SetVect,15H
  370.     mov    ax,76*100H + 0        ;Terminate, no error
  371.     int    21H
  372.  
  373. ;************************************************************
  374. ;
  375. ;Initialization code
  376. ;
  377. ;Each module can have its own initialization code.  The module simply
  378. ;puts the code in InitSeg.  All InitSegs are combined end-to-end,
  379. ;thus executing the init code for each module.  The RET instruction in
  380. ;LastSeg, immediately following InitSeg, returns program flow back to
  381. ;the caller of Init.
  382. ;
  383. ;All this code is thrown away when memory is resized.
  384.  
  385. InitSeg    segment
  386.     assume    cs:DGroup,ds:Dgroup
  387.  
  388. Init:
  389. ;one-time register initialization
  390.     DOS    SetVect,BreakVect,<offset DGroup:Interrupt>
  391.     DOS    GetVect,15H
  392.     mov    word ptr [NextInt15],bx
  393.     mov    word ptr [NextInt15+2],es
  394.     push    ds
  395.     pop    es
  396.     DOS    SetVect,15H,<offset DGroup:SysReq>
  397.     mov    [TestPSP],cs        ;Use our own PSP until program loads
  398.     xor    ax,ax
  399.     mov    di,offset DGroup:AxSave
  400.     mov    cx,8            ;Init all general registers
  401. rep    stosw
  402.     mov    ax,cs
  403.     mov    bx,offset DGroup:InitSeg
  404.     mov    cl,4
  405.     shr    bx,cl
  406.     add    ax,bx
  407. rep    stosw                ;Fill 4 segment registers
  408.     mov    ax,100H
  409.     stosw                ;Set IP
  410.     mov    ah,2
  411.     stosw                ;Enable user interrupts
  412.     mov    byte ptr [SpSave+1],1    ;Set user SP to 100H
  413. ;Will now fall into next module's init code
  414. InitSeg    ends
  415.  
  416.     END    Monitor
  417.