home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / assemblr / library / sampler0 / wt.asm < prev    next >
Assembly Source File  |  1987-03-12  |  23KB  |  471 lines

  1.         TITLE   WalkTree - Execute Program at Every Level of Tree
  2.  
  3. ; Copyright Notice:
  4. ; The program WalkTree,  both in binary executable and source forms,  is 
  5. ; in  the  public  domain.  No  warranty  is  given  or implied,  and no 
  6. ; liability will be assumed by the author.  
  7. ; Everyone on earth is hereby given permission to use, copy, distribute, 
  8. ; change, mangle,  destroy or otherwise employ these programs,  in whole 
  9. ; or in part,  in any fashion they so desire,  provided they hurt no one 
  10. ; but themselves in the process.  
  11. ; If anyone has any questions about this or any  other  program  that  I 
  12. ; have  authored,  I  can be reached by messages on any of the following 
  13. ; systems: 
  14. ;     Bob's Answering Machine      (602) 242-3158   300/1200 bps
  15. ;     FIDO 114/1 Phoenix Node      (602) 242-5230   300/1200/2400 bps
  16. ;     FIDO 114/446 XTRA #1         (602) 979-6352   300/1200/2400 bps
  17. ;     Technoids Anonymous          (602) 899-4876   300/1200/2400 bps
  18. ; All excellent 24 hour systems.
  19. ; Don A. Williams
  20. ; 3913 W. Solano Dr. N.
  21. ; Phoenix, AZ 85019
  22.  
  23.  
  24. ; This version of the source for WalkTree has been set up for assembly by
  25. ; SpeedWare's very good TurboEditAsm.  To convert it for assembly by
  26. ; Microsoft's MASM will require the addition of Segment and Assume
  27. ; statements, at least.
  28. ;
  29. ;
  30. ;   version history
  31. ;   modified by John Covici
  32. ;   3 Wirt Street NW
  33. ;   Leesburg, VA 22075
  34. ;   March 12, 1987 fixed the following bugs: 
  35. ;     (1) append cr to generated command line (if not dos goes out to lunch)
  36. ;     (2) now assembles with masm
  37. ;     (3) to get environment segment had to say [ds:2ch] instead of [2ch]
  38. ;        otherwise assembler ignored brackets without error
  39.  
  40. LF      EQU     0AH                     ; ASCII Line Feed
  41. CR      EQU     0DH                     ; ASCII Carriage Return
  42.  
  43.  
  44. cseg segment para public 'code'
  45.         ORG     0100H
  46.  assume cs:cseg,ds:cseg,ss:cseg
  47. Start:  jmp     Begin                   ; Jump over data area
  48.  
  49. ;------  Messages
  50.  
  51. LogOn   db      'WalkTree:  Version 1.01 - March 12, 1987',CR,LF,LF,'$'
  52.  
  53. BadVer  db      'WalkTree requires Dos 2.0 or greater',CR,LF,'$'
  54.  
  55. UseMsg  db      'USAGE:  WalkTree <any dos command>',CR,LF,'$'
  56.  
  57. EndMs1  db      CR,LF,'Number of directories= $'
  58. EndMs2  db      ': Maximum depth= $'
  59. EndMsg  db      '$'
  60.  
  61. AbtMsg  db      'Program terminated by operator.',CR,LF,'$'
  62.  
  63. ;------ Constants and Other Data Storage
  64.  
  65. Path    db      0,':\',65 DUP(0)
  66.  
  67. PatMsg  db      CR,LF,LF,'---'
  68. CurPat  db      0,':\',65 DUP(0)
  69. PatTer  db      '---',CR,LF,0
  70.  
  71.  
  72. MatAll  db      '*.*',0
  73.  
  74. Parent  db      '..',0
  75.  
  76. CmdTail db      0,'/c '
  77. CmdLin  db      128 DUP(0)
  78.  
  79. ComSpc  db      'COMSPEC',0
  80.  
  81. ComCom  db      '\COMMAND.COM',0
  82.  
  83. DTAOfs  dw      0                       ; Save space for DTA: Offset and
  84. DTASeg  dw      0                       ; ... Segment
  85.  
  86. SaveSS  dw      0                       ; Save space for Stack; Segment and
  87. SaveSP  dw      0                       ; ... Pointer
  88.  
  89. Level   dw      0                       ; Current depth in hierarchy
  90. MaxLev  dw      0                       ; Maximum depth in hierarchy
  91.  
  92. DirCnt  dw      0                       ; Count of directories processed
  93. comand db 65 dup(0) ;space for command.com from env or default
  94.  
  95. ;------  Parameter Block for DOS function 4B, Exec
  96.  
  97. ParBlk  dw      0                       ; Seg of environment string
  98.         dw      0                       ; Ofs of Command Tail string
  99.         dw      0                       ; Seg "     "      "     "
  100.         dw      0                       ; Ofs of Default FCB 1
  101.         dw      0                       ; Seg "     "     "  "
  102.         dw      0                       ; Ofs of Default FCB 2
  103.         dw      0                       ; Seg "     "     "  "
  104.  
  105. ;=========================================================================
  106. ; Beginning of Program Code
  107.  
  108. Begin:  mov     SP,offset STACK         ; Set local stack
  109.         cld                             ; Clear Direction Flag [forward]
  110.         mov     DX,offset LogOn         ; Dsiplay logon message
  111.         mov     AH,9                    ; ... MS-DOS 'Print String'
  112.         int     21H                     ; ... DOS Entry Interrupt
  113.         mov     AH,30H                  ; MS-DOS 'Get Version'
  114.         int     21H                     ; ... DOS Entry Interrupt
  115.         cmp     AL,2                    ; Check for 2.x or greater
  116.         jnb     VerOk                   ; ... Xfr- 2.x or greater
  117.         mov     DX,offset BadVer        ; Get ptr to 'bad version' msg
  118. ErrorExit:
  119.         mov     AH,9                    ; MS-DOS 'Print String'
  120.         int     21H                     ; ... DOS Entry Interrupt
  121.         int     20H                     ; DOS Terminate Program Interrupt
  122.  
  123. VerOk:  mov     AH,19H                  ; MS-DOS 'Get Current Disk'
  124.         int     21H                     ; ... DOS Entry Interrupt
  125.         add     AL,'A'                  ; Convert disk code to alpha disk
  126.         mov     Path,AL                 ; ... and save in Path
  127.         mov     CurPat,AL               ; ... and in Current Path
  128.         mov     SI,offset Path+3        ; Get Current Dir as starting path
  129.         mov     DL,0                    ; ... current disk
  130.         mov     AH,47H                  ; ... MS-DOS 'Get Current Directory'
  131.         int     21H                     ; ... DOS Entry Interrupt
  132.         mov     SI,80H                  ; Get ptr to Command Line buffer
  133.         lodsb                           ; ... and get length
  134.         or      AL,AL                   ; Check for length zero - no tail
  135.         jnz     HaveTail                ; ... Xfr - length not zero
  136. Usage:
  137.         mov     DX,offset UseMsg        ; Display 'Usage' message and
  138.         jmp     short ErrorExit         ; ... terminate
  139.  
  140. HaveTail:
  141.         cbw                             ; Make length 16 bits
  142.         mov     CX,AX                   ; ... and move to CX for move
  143.         add     AL,3                    ; Adjust length for '/c '
  144.         mov     CmdTail,AL              ; ... and store for DOS 4BH
  145.         mov     DI,offset CmdLin        ; Get ptr to internal Cmnd Line
  146.         repz    movsb                   ; Move command line to internal store
  147.  mov byte ptr[di],0dh ;append carriage return
  148.         mov     BX,1000H                ; Release all but 1000H paragraphs
  149.         mov     AH,4AH                  ; ... MS-DOS 'Modify Allocated Memory'
  150.         int     21H                     ; ... DOS Entry Interrupt
  151.         call    WalkTree                ; Walk the tree recursively
  152.         mov     DX,offset EndMs1        ; Print out run statistics
  153.         mov     AH,9                    ; ... MS-DOS 'Print String'
  154.         int     21H                     ; ... DOS Entry Interrupt
  155.         mov     BX,DirCnt               ; Display directory count in
  156.         call    PrintDecimal            ; ... decimal
  157.         mov     DX,offset EndMs2        ; Display 2nd part of message
  158.         mov     AH,9                    ; ... MS-DOS 'Print String'
  159.         int     21H                     ; ... DOS Entry Interrupt
  160.         mov     BX,MaxLev               ; Display maximum level in
  161.         call    PrintDecimal            ; ... decimal
  162.         mov     DX,offset EndMsg        ; Get ptr final part of message
  163. Terminate:
  164.         mov     AH,9                    ; MS-DOS 'Print String'
  165.         int     21H                     ; ... DOS Entry Interrupt
  166.         mov     DX,offset Path          ; Restore directory to starting
  167.         mov     AH,3BH                  ; ... MS-DOS 'Change Subdirectory'
  168.         int     21H                     ; ... DOS Entry Interrupt
  169.         int     20H                     ; DOS Terminate Program
  170.  
  171. ;=========================================================================
  172. ; WalkTree is a recursive subroutine that processes each level of the
  173. ; directory hierarchy.  Each invocation of Walktree creates and uses a
  174. ; 50 byte stack frame containing the Segment and Offset of the prior
  175. ; level's DTA, the name of the current subdirectory, and a pointer to its
  176. ; own stack frame.
  177.  
  178. WalkTree:
  179.         mov     SI,offset CurPat+3      ; Get current directory name
  180.         mov     DL,0                    ; ... current disk
  181.         mov     AH,47H                  ; ... MS-DOS 'Get Current Directory'
  182.         int     21H                     ; ... DOS Entry Interrupt
  183.         mov     SI,offset PatMsg        ; Display Current directory
  184.         call    PrintString             ; ...
  185.         mov     SI,offset PatTer        ; Terminate Current directory
  186.         call    PrintString             ; ...
  187.         inc     DirCnt                  ; Incr count of directories
  188.         mov     AX,Level                ; Incr level
  189.         inc     AX                      ; ...
  190.         mov     Level,AX                ; ... and store updated value
  191.         cmp     AX,MaxLev               ; Update Maximum level, if necessary
  192.         jbe     WT1                     ; ... Xfr - not necessary
  193.         mov     MaxLev,AX               ; ...
  194. WT1:    push    BP                      ; Save old stack frame ptr
  195.         sub     SP,49                   ; ... and get new stack frame
  196.         mov     BP,SP                   ; ...
  197.         add     BP,4                    ; ... leave room for DTA adr
  198.         push    ES                      ; Save ES over DOS call
  199.         mov     AH,2FH                  ; MS-DOS 'Get DTA'
  200.         int     21H                     ; DOS Entry Interrupt
  201.         mov     [BP-4],BX               ; Save DTA offset and DTA segment
  202.         mov     [BP-2],ES               ; ... in stack frame
  203.         pop     ES                      ; Restore saved ES
  204.         mov     DX,BP                   ; Set DTA to Stack frame
  205.         mov     AH,1AH                  ; ... MS-DOS 'Set DTA'
  206.         int     21H                     ; ... DOS Entry Interrupt
  207.         call    CheckAbort              ; Check for operator abort
  208.         call    Execute
  209.         mov     DX,offset MatAll        ; Get ptr to ALL match string
  210.         mov     CX,10H                  ; ... set attribute for Subdirectory
  211.         mov     AH,4EH                  ; ... MS-DOS 'Find 1st Match'
  212.         int     21H                     ; ... DOS Entry Interrupt
  213.         jb      PopLevel                ; ... Xfr - Had error
  214. ProcessSub:
  215.         test    byte ptr [BP+21],10H    ; Check for Subdirectory
  216.         jz      GetNextSub              ; ... Xfr - not Subdirectory
  217.         cmp     byte ptr [BP+30],'.'    ; Check for 'parent' or 'self' entries
  218.         jz      GetNextSub              ; ... Xfr - 'parent' or 'self'
  219.         mov     DX,BP                   ; Get ptr to DTA
  220.         add     DX,30                   ; ... and compute name ptr
  221.         mov     AH,3BH                  ; MS-DOS 'Change SubDirectory'
  222.         int     21H                     ; ... DOS Entry Interrupt
  223.         call    CheckAbort              ; Check for operator abort
  224.         call    WalkTree                ; Walk the tree of new directory
  225. GetNextSub:
  226.         mov     AH,4FH                  ; MS-DOS 'Find Next Match'
  227.         mov     CX,10H                  ; ... set attribute for directory
  228.         int     21H                     ; ... DOS Entry Interrupt
  229.         jb      PopLevel                ; ... Xfr - error - no more matches
  230.         jmp     short ProcessSub        ; Loop through directory
  231.  
  232. PopLevel:
  233.         mov     DX,offset Parent        ; Get ptr to 'Parent' string
  234.         mov     AH,3BH                  ; ... MS-DOS 'Change SubDirectory'
  235.         int     21H                     ; ... DOS Entry Interrupt
  236.         push    DS                      ; Save DS
  237.         mov     DS,[BP-2]               ; Restore prior DTA from stack
  238.         mov     DX,[BP-4]               ; ... frame
  239.         mov     AH,1AH                  ; MS-DOS 'Set DTA'
  240.         int     21H                     ; ... DOS Entry Interrupt
  241.         pop     DS                      ; Restore saved DS
  242.         dec     Level                   ; Decr directory level count
  243.         add     SP,49                   ; Delete stack frame
  244.         pop     BP                      ; Restore stack frame ptr
  245.         ret
  246.  
  247. ; End of WalkTree
  248. ;-------------------------------------------------------------------------
  249.  
  250. ;=========================================================================
  251. ; CheckAbort is used to check for an Operator Abort [any key pressed
  252. ; during execution.
  253.  
  254. CheckAbort:
  255.         mov     AH,0BH                  ; MS-DOS 'Check StdIn Status'
  256.         int     21H                     ; ... DOS Entry Interrupt
  257.         or      AL,AL                   ; Check for Char ready
  258.         jz      CAExit                  ; ... Xfr - no char ready
  259.         mov     AH,08H                  ; MS-DOS 'Console In, No Echo'
  260.         int     21H                     ; ... DOS Entry Interrupt
  261.         mov     DX,offset AbtMsg        ; Get ptr to 'abort' message
  262.         jmp     Terminate               ; ... and terminate program
  263.  
  264. CAExit: ret
  265.  
  266. ; End of CheckAbort
  267. ;-------------------------------------------------------------------------
  268.  
  269. ;=========================================================================
  270. ; Execute is used to execute the program specified on WalkTree's Command
  271. ; line.  It uses MS-DOS Function 21H, SubFunction 4BH [Exec] to execute
  272. ; COMMAND.COM as a child.  It searches the Environment to find COMSPEC
  273. ; in order to call COMMAND.COM
  274.  
  275. Execute:
  276.         push    BP                      ; Save caller's registers
  277.         push    DS                      ; ...
  278.         push    ES                      ; ...
  279.         push    ES                      ; Save ES over CALL
  280.         mov     AH,2FH                  ; MS-DOS 'Get DTA'
  281.         int     21H                     ; ... DOS Entry Interrupt
  282.         mov     DTASeg,ES               ; Save DTA segment
  283.         mov     DTAOfs,BX               ; ... and Offset
  284.         pop     ES                      ; Restore saved ES
  285.         mov     AX,CS                   ; Get segment for DOS 4B
  286.         mov     ParBlk+4,AX             ; ... and store as Command Tail Seg
  287.         mov     ParBlk+8,AX             ; ... and as FCB 1 Seg
  288.         mov     ParBlk+12,AX            ; ... and as FCB 2 Seg
  289.         mov     ParBlk+2,offset CmdTail ; Store offset of Cmnd Tail
  290.         mov     ParBlk+6,5CH            ; ... and offset of FCB 1
  291.         mov     ParBlk+10,6CH           ; ... and offset of FCB 2
  292.         mov     DI,offset ComSpc
  293.    mov bx,[ds:2ch] ;get environment string segment
  294.         mov     ParBlk,BX               ; ... to Parameter Blk for DOS 4BH
  295.         call    FindComSpec             ; Search environment for COMSPEC
  296.         jnc     GotComSpec              ; ... Xfr - found COMSPEC
  297.         mov     AX,CS                   ; Set DS to local data space
  298.         mov     DS,AX                   ; ...
  299.    mov dx, offset ComCom ;get ptr to 'command.com'
  300.  jmp short goexec
  301. GotComSpec:
  302.  mov di,offset comand ; dest offset of comand in di
  303.  mov cl,65;large enough number
  304. smov1:
  305.  lodsb ;load byte in al
  306.  stosb ;store byte in comand
  307.  or al,al
  308.  loopnz smov1
  309.         mov     AX,CS                   ; Set DS to local data space
  310.         mov     DS,AX                   ; ...
  311.  mov dx,offset comand;file name to execute
  312. goexec:
  313.         mov     BX,offset ParBlk        ; Get ptr to Parameter Block for DOS 4BH
  314.         mov     CS:SaveSS,SS            ; Save Stack Segment & offset over
  315.         mov     CS:SaveSP,SP            ; ... Exec call
  316.         mov     AX,4B00H                ; MS-DOS 'Load & Execute Program'
  317.         int     21H                     ; ... DOS Entry Interrupt
  318.         cli                             ; Inhibit interrupts
  319.         mov     SS,CS:SaveSS            ; Restore Stack Segment &
  320.         mov     SP,CS:SaveSP            ; ... Offset
  321.         sti                             ; Enable interrupts
  322.         mov     DS,CS:DTASeg            ; Restore local data space
  323.         mov     DX,CS:DTAOfs
  324.         mov     AH,1AH                  ; MS-DOS 'Set DTA'
  325.         int     21H                     ; ... DOS Entry Interrupt
  326.         pop     ES
  327.         pop     DS
  328.         pop     BP
  329.         ret
  330.  
  331. ; End of Execute
  332. ;-------------------------------------------------------------------------
  333.  
  334. ;=========================================================================
  335. ; FindComSpec is used by Execute to locate COMSPEC in the Environment and
  336. ; the name of COMMAND.COM to pass to MS-DOS 21H, SubFunction 4B [Exec].
  337.  
  338. FindComSpec:
  339.         mov     DS,BX                   ; Set data space to Environment
  340.         mov     DI,offset ComSpc        ; Get ptr to 'COMSPEC' for search
  341.         sub     SI,SI                   ; Start at relative 0 in Environment
  342.         mov     CX,7                    ; Get length of 'COMSPEC'
  343.  
  344. XFCS3:  lodsb                           ; Get byte from Environment
  345.         or      AL,AL                   ; Check for end of entry
  346.         jnz     XFCS4                   ; ... Xfr - not end of entry
  347.         cmp     byte ptr [SI+1],0       ; Check for end of Environment
  348.         jz      XFCS5                   ; ... Xfr - end of Environment
  349. XFCS4:  call    UpCase                  ; Convert to upper case and
  350.         mov     [SI-1],AL               ; ... store back in Environment
  351.         cmp     AL,'='                  ; Check for '=' as in 'COMSPEC='
  352.         jnz     XFCS3                   ; ... Xfr - not '='
  353.         push    SI                      ; Save both ptrs and length
  354.         push    DI                      ; ...
  355.         push    CX                      ; ...
  356.         sub     SI,2                    ; Back up SI to end of string
  357.         std                             ; Set Direction Flag [reverse]
  358.         repnz   cmpsb                   ; Compare Envirn string to 'COMSPEC'
  359.         cld                             ; Clear Direction Flag [forward]
  360.         pop     CX                      ; Restore length and both ptrs
  361.         pop     DI                      ; ...
  362.         pop     SI                      ; ...
  363.         jnz     XFCS3                   ; Xfr - did not match 'COMSPEC'
  364.         clc                             ; Clear CARRY for good return
  365.         ret
  366.  
  367. XFCS5:  stc                             ; Set CARRY for error return
  368.         ret
  369.  
  370. ; End of FindComSpec
  371. ;-------------------------------------------------------------------------
  372.  
  373. ;=========================================================================
  374. ; UpCase is a utility subroutine to convert the lower case alpha char in
  375. ; AL to upper case.  Only lower case alphas are affected, any other char
  376. ; in AL is returned unmodified.
  377.  
  378. UpCase: cmp     AL,'a'                  ; Check upper bound of lower case
  379.         jb      UCExit                  ; ... Xfr - not lower case - too low
  380.         cmp     AL,'z'                  ; Check upper bound of lower case
  381.         ja      UCExit                  ; ... Xfr - not lower case - too high
  382.         and     AL,0DFH                 ; Convert char to upper case
  383. UCExit: ret
  384.  
  385. ;End of UpCase
  386. ;-------------------------------------------------------------------------
  387.  
  388. ;=========================================================================
  389. ; PrintDecimal is a utility subroutine used to convert the 16-bit integer
  390. ; in BX to decimal and display it on StdOut as a 5-digit figure with
  391. ; blank suppression of leading zeros.  It is overkill for the current
  392. ; version of WalkTree.
  393.  
  394. PrintDecimal:
  395.         mov     CL,0
  396.         mov     DX,10000                ; Get 10,000s digit and display
  397.         call    PrintDigit              ; ... it
  398.         mov     DX,1000                 ; Get 1,000s digit and display
  399.         call    PrintDigit              ; ... it
  400.         mov     DX,100                  ; Get 100s digit and display
  401.         call    PrintDigit              ; ... it
  402.         mov     DX,10                   ; Get 10s digit and display
  403.         call    PrintDigit              ; ... it
  404.         mov     CH,BL                   ; Display units digit [no zero
  405.         jmp     short XPD2              ; ... suppression]
  406.  
  407. PrintDigit:
  408.         mov     CH,0FFH                 ; Initialize result
  409. XPD1:   inc     CH                      ; Incr result
  410.         sub     BX,DX                   ; Divide by repetitive subtraction
  411.         jnb     XPD1                    ; ... Xfr - not there yet
  412.         add     BX,DX                   ; Correct for overshoot
  413.         cmp     CH,0                    ; Check result for zero
  414.         jnz     XPD2                    ; ... Xfr - not zero result
  415.         test    CL,1                    ; Test for leading zero
  416.         jnz     XPD2                    ; ... Xfr - not leading zero
  417.         ret
  418.  
  419. XPD2:   push    DX                      ; Save divisor
  420.         mov     DL,CH                   ; Move digit to DL for DOS
  421.         add     DL,'0'                  ; Convert digit to ASCII
  422.         mov     AH,2                    ; MS-DOS 'Console Output
  423.         int     21H                     ; ... DOS ENtry Interrupt
  424.         pop     DX                      ; Restore divisor
  425.         mov     CL,1                    ; Turn OFF zero suppression
  426.         ret
  427.  
  428. ; End of PrintDecimal
  429. ;-------------------------------------------------------------------------
  430.  
  431. ;=========================================================================
  432. ; PrintString is a utility subroutine to display a NULL-terminated ASCII
  433. ; string on StdOut.  On input, SI contains the address of the string to
  434. ; be displayed.  All other registers are preserved.
  435.  
  436. PrintString:
  437.         push    AX
  438.         push    DX
  439.  
  440. PS1:    lodsb
  441.         or      AL,AL
  442.         jz      PSExit
  443.         mov     DL,AL
  444.         mov     AH,02H
  445.         int     21H
  446.         jmp     short PS1
  447.  
  448. PSExit: pop     DX
  449.         pop     AX
  450.         ret
  451.  
  452. ;End of PrintString
  453. ;-------------------------------------------------------------------------
  454.  
  455. ;=========================================================================
  456. ; Stack space.  Since each invocation of the WalkTree subroutine creates a
  457. ; 50 byte stack frame on this stack, 3000 bytes of stack would allow for
  458. ; approximately 60 levels in the directory hierarchy, probably extreme
  459. ; overkill.
  460.  
  461. STACK   EQU     $+3000
  462.  
  463. cseg ends
  464.         end     Start
  465.