home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
assemblr
/
asm
/
chasm
/
wc.asm
< prev
next >
Wrap
Assembly Source File
|
1986-02-04
|
12KB
|
366 lines
;================================================
; PROGRAM WC Version 1.1 by Dave Whitman
;
; Filter to count words, lines and characters.
; Based loosely on Kernighan and Ritchie, page 18.
;
; Syntax: WC [?] [/w] [/l] [/c]
;
; ? = print help message
; /w = unlabeled word count
; /l = unlabeled line count
; /c = unlabeled character count
; none = combined counts, with labels
;
; The three options may be present in any combination.
; Regardless of option order, the selected counts will
; be in the following order:
; words
; lines
; characters
;
; Requires DOS 2.0, will abort under earlier versions.
;====================================================
;============
; Equates
;============
@read equ 3FH ;read file/device
@chrin equ 06H ;get char from stdin
@chrout equ 02H ;send char to stdout
@dosver equ 30H ;get dos version
@prnstr equ 09H ;print string
stdin equ 0000H ;standard input
w equ 01H ;flag value for word option
l equ 02H ;flag value for line option
c equ 04H ;flag value for char option
yes equ 0FFH ;boolean value
no equ 00H ; "
cr equ 0DH ;carriage return
lf equ 0AH ;line feed
\n equ 0DH ;newline char
\t equ 09H ;tab char
\l equ 0AH ;linefeed char
buf_size equ 8192
mem_avail equ [06H]
param_count equ [80H]
param_area equ [81H]
main proc far
call setup ;check dos, parse options
call buf_in ;count w, l, c from std i/o
call output ;send requested output
int 20H ;and return to dos
endp
;======================================
; SUBROUTINE SETUP
; Checks for proper DOS, parses options
;======================================
setup proc near
mov ah, @dosver ;what dos are we under?
int 21H
cmp al, 2 ;2.0 or over?
jae a0 ;yes, skip
mov ah, @prnstr ;no, bitch
mov dx, offset(baddos)
int 21H
pop ax ;reset stack
int 20H ;and exit
a0 mov ax, mem_avail ;do we have room for the buffer?
cmp ax, buf_size
jae a1 ;yes, skip
mov ah, @prnstr ;no, bitch
mov dx, offset(nomem)
int 21H
pop ax ;reset stack
int 20H ;and exit
a1 xor ch,ch ;cx <== param count
mov cl, param_count ; "
cmp cl, 00H ;any params?
je aexit ;exit if none
mov di, offset(param_area) ;scan for help request
mov al, '?' ;marked with ?
repnz ;scan until match or end
scasb
jnz a_par ;reached end, no match? skip
mov ah, @prnstr ;matched? print help
mov dx, offset(help)
int 21H
pop ax ;pop stack and exit
int 20H
a_par xor ch, ch ;get number of param chars again
mov cl, param_count
mov di, offset(param_area) ;scan for options
a2 mov al, '/' ;will be marked with /
repnz
scasb
jnz aexit ;reached end
mov al, [di] ;get option char
and al, 0DFH ;guarantees upper case
cmp al, 'W' ;words?
jne a3 ;nope
orb options, w ;yes, set flag
jmps a2 ;and loop
a3 cmp al, 'L' ;lines?
jne a4 ;nope
orb options, l ;yes, set flag
jmps a2 ;and loop
a4 cmp al, 'C' ;characters?
jne a2 ;nope, just loop
orb options, c ;yes, set flag
jmps a2 ;and loop
aexit ret
baddos db cr lf 'This program requires DOS 2.0!' cr, lf, '$'
nomem db cr lf 'Insufficient memory, program aborted' cr lf '$'
help db cr lf
db 'WC version 1.2 by D. Whitman' cr lf
db cr lf
db 'Reads StdIn, and writes count of words, lines,' cr lf
db 'and characters to StdOut.' cr lf
db cr lf
db 'Syntax:' cr lf
db cr lf
db ' WC [?] [/W] [/L] [/C] [<infile] [>outfile]' cr lf
db cr lf
db ' Options:' cr lf
db ' ? = print this help message' cr lf
db ' /W = print unlabeled word count' cr lf
db ' /L = print unlabeled line count' cr lf
db ' /C = print unlabeled character count' cr lf
db ' none = combined counts, with labels' cr lf
db cr lf
db 'Multiple options can be selected.' cr lf
db cr lf
db 'This program is in the public domain.' cr lf '$'
endp
;=========================================
; SUBROUTINE BUF_INPUT
; Inputs data by sector, sends it one char
; at a time for counting.
;==========================================
buf_in proc near
movb inword, no ;not currently in a word
bu1 mov ah, @read ;read
mov bx, stdin ;from stdin
mov cx, buf_size ;one buffer's worth
mov dx, offset(buffer)
int 21H
cmp ax, 00H ;test for EOF
jz buexit ;if so, done
mov cx,ax ;cx <== number chars read
mov si, offset(buffer)
bu2 lodsb ;al <== next char from buffer
call count ;update totals
loop bu2
jmps bu1
buexit ret
endp
;=============================================
;SUBROUTINE COUNT
;Counts words, lines and characters as per K&R
;=============================================
count proc near
addw clow,0001H ;bump # of chars
jae b1 ;no carry? skip
incw chigh ;handle carry
;in the following, note use of ADD to increment
;doublewords. INC does not affect Carry Flag.
b1 cmp al, \n ;is it a newline?
jne b2 ;no, skip
addw llow,0001H ;bump # of lines
jae b2 ;no carry? skip
incw lhigh ;handle carry
b2 cmp al, \n ;newline or
je b3
cmp al, \t ;tab or
je b3
cmp al, \l ;linefeed or
je b3
cmp al, ' ' ;blank,
je b3 ;then skip
;none of the above
cmpb inword, yes ;already in a word?
je b4 ;yes, return
movb inword, yes ;if not, we are now.
addw wlow,0001H ;bump word count
jae b4 ;no carry? return
incw whigh ;handle carry
jmps b4 ;return
;any of the above
b3 movb inword, no
b4 ret
endp
;=====================================
; SUBROUTINE OUTPUT
; Prints results, modified by options.
;=====================================
output proc near
cmpb options, 00H ;any options?
jne c1 ;yes, skip label
mov ah, @prnstr ;print label for word count
mov dx, offset(word_label)
int 21H
jmps c1a ;print count
c1 testb options, W ;/w option?
jz c2 ;nope, skip
c1a mov di, whigh ;get doubleword word count
mov si, wlow ; in di:si
call printdd ;convert and print it.
call newline
c2 cmpb options, 00H ;any options?
jne c3 ;yes, skip label
mov ah, @prnstr ;print label for line count
mov dx, offset(line_label)
int 21H
jmps c3a ;print count
c3 testb options, L ;/l option?
jz c4 ;nope, skip
c3a mov di, lhigh ;get doubleword line count
mov si, llow ; in di:si
call printdd ;convert and print it
call newline
c4 cmpb options, 00H ;any options?
jne c5 ;yes, skip label
mov ah, @prnstr ;print label for char count
mov dx, offset(char_label)
int 21H
jmps c5a ;print count
c5 testb options, C ;/c option?
jz c6 ;nope, skip
c5a mov di, chigh ;get doubleword char count
mov si, clow ; in di:si
call printdd ;convert and print it
call newline
c6 ret
word_label db 'Words: $'
line_label db 'Lines: $'
char_label db 'Chars: $'
endp
;=========================
; SUBROUTINE NEWLINE
; Prints a CR/LF to stdout
;=========================
newline proc near
mov ah, @prnstr
mov dx, offset(crlf)
int 21H
ret
crlf db 0DH, 0AH, '$'
endp
;=========================================================
; SUBROUTINE PRINTDD
; This less-than-comprehensible routine was swiped verbatim
; from Ted Reuss's disassembly of John Chapman's sorted
; disk directory program. The routine converts a 32 bit
; integer in DI:SI to ASCII digits and sends them to STDOUT.
;==========================================================
PRINTDD PROC NEAR ;Prints a 32 bit integer in DI:SI
XOR AX,AX ;Zero out the
MOV BX,AX ; working
MOV BP,AX ; registers.
MOV CX,32 ;# bits of precision
J1 SHL SI
RCL DI
XCHG BP,AX
CALL J6
XCHG BP,AX
XCHG BX,AX
CALL J6
XCHG BX,AX
ADC AL,0
LOOP J1
MOV CX,1710H ;5904 ?
MOV AX,BX
CALL J2
MOV AX,BP
J2 PUSH AX
MOV DL,AH
CALL J3
POP DX
J3 MOV DH,DL
SHR DL ;Move high
SHR DL ; nibble to
SHR DL ; the low
SHR DL ; position.
CALL J4
MOV DL,DH
J4 AND DL,0FH ;Mask low nibble
JZ J5 ;If not zero
MOV CL,0
J5 DEC CH
AND CL,CH
OR DL,'0' ;Fold in ASCII zero
SUB DL,CL
MOV AH, @CHROUT ;Print next digit
INT 21H
RET ;Exit to caller
ENDP
J6 PROC NEAR
ADC AL,AL
DAA
XCHG AL,AH
ADC AL,AL
DAA
XCHG AL,AH
RET
ENDP
;=================
;GLOBAL VARIABLES
;=================
options db 00H ;byte of option flags
inword db 00H ;flag: yes indicates scan is within a word
wlow db 00H, 00H ;low part of doubleword word count
whigh db 00H, 00H ;high " " " " "
llow db 00H, 00H ;low part of doubleword line count
lhigh db 00H, 00H ;high " " " " "
clow db 00H, 00H ;low part of doubleword char count
chigh db 00H, 00H ;high " " " " "
buffer ;input buffer