home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast2.iso / asmutil / chasm4.zip / WC.ASM < prev    next >
Assembly Source File  |  1983-11-17  |  10KB  |  315 lines

  1. ;================================================
  2. ; PROGRAM WC    Version 1.1 by Dave Whitman
  3. ;
  4. ; Filter to count words, lines and characters.
  5. ; Based loosely on Kernighan and Ritchie, page 18.
  6. ;
  7. ; Syntax:  WC [/w] [/l] [/c]
  8. ;
  9. ;          /w = unlabeled word count
  10. ;          /l = unlabeled line count
  11. ;          /c = unlabeled character count
  12. ;        none = combined counts, with labels
  13. ;
  14. ; The three options may be present in any combination.
  15. ; Regardless of option order, the selected counts will
  16. ; be in the following order:
  17. ;    words
  18. ;    lines
  19. ;    characters
  20. ;
  21. ; Requires DOS 2.0, will abort under earlier versions.
  22. ;====================================================
  23.  
  24. ;============
  25. ; Equates
  26. ;============
  27.  
  28. @read   equ    3FH             ;read file/device
  29. @chrin  equ    06H             ;get char from stdin
  30. @chrout equ    02H             ;send char to stdout
  31. @dosver equ    30H             ;get dos version
  32. @prnstr equ    09H             ;print string
  33.  
  34. stdin   equ    0000H           ;standard input
  35. w       equ    01H             ;flag value for word option
  36. l       equ    02H             ;flag value for line option
  37. c       equ    04H             ;flag value for char option
  38. yes     equ    0FFH            ;boolean value
  39. no      equ    00H             ;    "
  40. \n      equ    0DH             ;newline char
  41. \t      equ    09H             ;tab char
  42. \l      equ    0AH             ;linefeed char
  43.  
  44. param_count    equ     [80H]
  45. param_area     equ     [81H]
  46.  
  47. main   proc    far
  48.        call    setup           ;check dos, parse options
  49.        call    buf_in          ;count w, l, c from std i/o
  50.        call    output          ;send requested output
  51.        int     20H             ;and return to dos
  52.        endp
  53.  
  54. ;======================================
  55. ; SUBROUTINE SETUP
  56. ; Checks for proper DOS, parses options
  57. ;======================================
  58. setup  proc    near
  59.  
  60.        mov     ah, @dosver     ;what dos are we under?
  61.        int     21H
  62.        cmp     al, 2           ;2.0 or over?
  63.        jae     a1              ;yes, skip
  64.  
  65.        mov     ah, @prnstr     ;no, bitch
  66.        mov     dx, offset(baddos)
  67.        int     21H
  68.        pop     ax              ;reset stack
  69.        int     20H             ;and exit
  70.  
  71. a1     xor     ch,ch           ;cx <== param count
  72.        mov     cl, param_count ;  "
  73.        cmp     cl, 00H         ;any params?
  74.        je      aexit           ;exit if none
  75.  
  76.        mov     di, offset(param_area)   ;scan for options
  77. a2     mov     al, '/'                  ;will be marked with /
  78.        repnz
  79.        scasb
  80.        jnz     aexit           ;reached end
  81.  
  82.        mov     al, [di]        ;get option char
  83.        and     al, 0DFH        ;guarantees upper case
  84.  
  85.        cmp     al, 'W'         ;words?
  86.        jne     a3              ;nope
  87.        orb     options, w      ;yes, set flag
  88.        jmps    a2              ;and loop
  89.  
  90. a3     cmp     al, 'L'         ;lines?
  91.        jne     a4              ;nope
  92.        orb     options, l      ;yes, set flag
  93.        jmps    a2              ;and loop
  94.  
  95. a4     cmp     al, 'C'         ;characters?
  96.        jne     a2              ;nope, just loop
  97.        orb     options, c      ;yes, set flag
  98.        jmps    a2              ;and loop
  99.  
  100. aexit  ret
  101.  
  102. baddos db      'This program requires DOS 2.0!' 0DH, 0AH, '$'
  103.        endp
  104.  
  105. ;=========================================
  106. ; SUBROUTINE BUF_INPUT
  107. ; Inputs data by sector, sends it one char
  108. ; at a time for counting.
  109. ;==========================================
  110.  
  111.  
  112. buf_in proc    near
  113.  
  114.        movb    inword, no      ;not currently in a word
  115.  
  116. bu1    mov     ah, @read       ;read
  117.        mov     bx, stdin       ;from stdin
  118.        mov     cx, 512         ;one sector's worth
  119.        mov     dx, offset(buffer)
  120.        int     21H
  121.        cmp     ax, 00H         ;test for EOF
  122.        jz      buexit          ;if so, done
  123.  
  124.        mov     cx,ax           ;cx <== number chars read
  125.        mov     si, offset(buffer)
  126. bu2    lodsb                   ;al <== next char from buffer
  127.        call    count           ;update totals
  128.        loop    bu2
  129.        jmps    bu1
  130. buexit ret
  131.        endp
  132.  
  133. ;=============================================
  134. ;SUBROUTINE COUNT
  135. ;Counts words, lines and characters as per K&R
  136. ;=============================================
  137. count  proc    near
  138.        addw    clow,0001H      ;bump # of chars
  139.        jae     b1              ;no carry? skip
  140.        incw    chigh           ;handle carry
  141.  
  142.        ;in the following, note use of ADD to increment
  143.        ;doublewords.  INC does not affect Carry Flag.
  144.  
  145. b1     cmp     al, \n          ;is it a newline?
  146.        jne     b2              ;no, skip
  147.        addw    llow,0001H      ;bump # of lines
  148.        jae     b2              ;no carry? skip
  149.        incw    lhigh           ;handle carry
  150.  
  151. b2     cmp     al, \n          ;newline or
  152.        je      b3
  153.        cmp     al, \t          ;tab or
  154.        je      b3
  155.        cmp     al, \l          ;linefeed or
  156.        je      b3
  157.        cmp     al, ' '         ;blank,
  158.        je      b3              ;then skip
  159.  
  160.       ;none of the above
  161.        cmpb    inword, yes     ;already in a word?
  162.        je      b4              ;yes, return
  163.        movb    inword, yes     ;if not, we are now.
  164.        addw    wlow,0001H      ;bump word count
  165.        jae     b4              ;no carry? return
  166.        incw    whigh           ;handle carry
  167.        jmps    b4              ;return
  168.  
  169.       ;any of the above
  170. b3     movb    inword, no
  171. b4     ret
  172.        endp
  173.  
  174. ;=====================================
  175. ; SUBROUTINE OUTPUT
  176. ; Prints results, modified by options.
  177. ;=====================================
  178. output proc    near
  179.  
  180.        cmpb    options, 00H    ;any options?
  181.        jne     c1              ;yes, skip label
  182.        mov     ah, @prnstr     ;print label for word count
  183.        mov     dx, offset(word_label)
  184.        int     21H
  185.        jmps    c1a             ;print count
  186.  
  187. c1     testb   options, W      ;/w option?
  188.        jz      c2              ;nope, skip
  189. c1a    mov     di, whigh       ;get doubleword word count
  190.        mov     si, wlow        ; in di:si
  191.        call    printdd         ;convert and print it.
  192.        call    newline
  193.  
  194. c2     cmpb    options, 00H    ;any options?
  195.        jne     c3              ;yes, skip label
  196.        mov     ah, @prnstr     ;print label for line count
  197.        mov     dx, offset(line_label)
  198.        int     21H
  199.        jmps    c3a             ;print count
  200.  
  201. c3     testb   options, L      ;/l option?
  202.        jz      c4              ;nope, skip
  203. c3a    mov     di, lhigh       ;get doubleword line count
  204.        mov     si, llow        ; in di:si
  205.        call    printdd         ;convert and print it
  206.        call    newline
  207.  
  208. c4     cmpb    options, 00H    ;any options?
  209.        jne     c5              ;yes, skip label
  210.        mov     ah, @prnstr     ;print label for char count
  211.        mov     dx, offset(char_label)
  212.        int     21H
  213.        jmps    c5a             ;print count
  214.  
  215. c5     testb   options, C      ;/c option?
  216.        jz      c6              ;nope, skip
  217. c5a    mov     di, chigh       ;get doubleword char count
  218.        mov     si, clow        ; in di:si
  219.        call    printdd         ;convert and print it
  220.        call    newline
  221.  
  222. c6     ret
  223.  
  224. word_label db 'Words:  $'
  225. line_label db 'Lines:  $'
  226. char_label db 'Chars:  $'
  227.       endp
  228.  
  229. ;=========================
  230. ; SUBROUTINE NEWLINE
  231. ; Prints a CR/LF to stdout
  232. ;=========================
  233. newline proc   near
  234.        mov     ah, @prnstr
  235.        mov     dx, offset(crlf)
  236.        int     21H
  237.        ret
  238. crlf   db      0DH, 0AH, '$'
  239.        endp
  240.  
  241. ;=========================================================
  242. ; SUBROUTINE PRINTDD
  243. ; This less-than-comprehensible routine was swiped verbatim
  244. ; from Ted Reuss's disassembly of John Chapman's sorted
  245. ; disk directory program.  The routine converts a 32 bit
  246. ; integer in DI:SI to ASCII digits and sends them to STDOUT.
  247. ;==========================================================
  248.  
  249. PRINTDD PROC    NEAR    ;Prints a 32 bit integer in DI:SI
  250.         XOR     AX,AX           ;Zero out the
  251.         MOV     BX,AX           ; working
  252.         MOV     BP,AX           ; registers.
  253.         MOV     CX,32           ;# bits of precision
  254. J1      SHL     SI
  255.         RCL     DI
  256.         XCHG    BP,AX
  257.         CALL    J6
  258.         XCHG    BP,AX
  259.         XCHG    BX,AX
  260.         CALL    J6
  261.         XCHG    BX,AX
  262.         ADC     AL,0
  263.         LOOP    J1
  264.         MOV     CX,1710H        ;5904 ?
  265.         MOV     AX,BX
  266.         CALL    J2
  267.         MOV     AX,BP
  268. J2      PUSH    AX
  269.         MOV     DL,AH
  270.         CALL    J3
  271.         POP     DX
  272. J3      MOV     DH,DL
  273.         SHR     DL              ;Move high
  274.         SHR     DL              ; nibble to
  275.         SHR     DL              ; the low
  276.         SHR     DL              ; position.
  277.         CALL    J4
  278.         MOV     DL,DH
  279. J4      AND     DL,0FH          ;Mask low nibble
  280.         JZ      J5              ;If not zero
  281.         MOV     CL,0
  282. J5      DEC     CH
  283.         AND     CL,CH
  284.         OR      DL,'0'          ;Fold in ASCII zero
  285.         SUB     DL,CL
  286.  
  287.         MOV     AH, @CHROUT     ;Print next digit
  288.         INT     21H
  289.  
  290.         RET                     ;Exit to caller
  291.         ENDP
  292.  
  293. J6     PROC    NEAR
  294.         ADC     AL,AL
  295.         DAA
  296.         XCHG    AL,AH
  297.         ADC     AL,AL
  298.         DAA
  299.         XCHG    AL,AH
  300.         RET
  301.         ENDP
  302.  
  303. ;=================
  304. ;GLOBAL VARIABLES
  305. ;=================
  306. options  db  00H       ;byte of option flags
  307. inword   db  00H       ;flag: yes indicates scan is within a word
  308. wlow     db  00H, 00H  ;low part of doubleword word count
  309. whigh    db  00H, 00H  ;high "   "      "       "     "
  310. llow     db  00H, 00H  ;low part of doubleword line count
  311. lhigh    db  00H, 00H  ;high "   "      "       "     "
  312. clow     db  00H, 00H  ;low part of doubleword char count
  313. chigh    db  00H, 00H  ;high "   "      "       "     "
  314. buffer                 ;input buffer
  315.