; W C . A S M (WORD COUNTER) ; DAVID COONS (CIS [72435,136]) ; V1.0 FEBRUARY 1984 ; ; ABSTRACT ; -------- ; COUNTS WORDS IN ANY FILE AND DISPLAYS ; COUNT ON CON: IN THE FORM "FILE CONTAINS ; 00000 WORDS.". A WORD IS DEFINED AS ANY ; CHARACTER SEQUENCE ENDED BY SPACES, TABS, ; A CARRIAGE RETURN, OR LINE FEED. IGNORES ; HIGH ORDER BIT IN ANY CHARACTER. ; USES WORD COUNT ALGORITHM FROM "THE C ; PROGRAMMING LANGUAGE" (BW KERNIGHAN AND DM ; RITCHIE, ENGLEWOOD CLIFFS, NJ: PRENTICE- ; HALL, 1978), PAGE 18. ; WRITTEN IN 8080 ASSEMBLY LANGUAGE ; (ASSEMBLE WITH ASM.COM) ; ; USAGE ; WC A:FILENAME.EXT ; (AMBIGUOUS FILE NAMES NOT ALLOWED) ; EXECUTION TIMING ; A 3200-WORD FILE WAS COUNTED IN ; APPROXIMATELY SEVEN SECONDS. ; -------------------------------------------------- YES EQU -1 NO EQU NOT YES ZERO EQU 0 BDOS EQU 0005H ;BDOS ENTRY ADDR RESET EQU 0 ;SYSTEM RESET CONOUT EQU 2 ;CONSOLE OUTPUT WRTSTR EQU 9 ;WRITE STRING CHKSTAT EQU 11 ;GET CONSOLE STATUS FOPEN EQU 15 ;OPEN FILE FCLOSE EQU 16 ;CLOSE FILE FREAD EQU 20 ;SEQUENTIAL READ SETBUF EQU 26 ;SET BUFFER ADDR FCB EQU 005CH ;FCB ADDR DRIVE EQU FCB ;DRIVE FILNAM EQU FCB+01H ;FILE NAME EXTENT EQU FCB+0CH ;EXTENT NUMBER CURREC EQU FCB+20H ;CURRENT RECORD BUFFER EQU 0080H ;DISK I/O BUFFER TAB EQU 09H ;HORIZONTAL TAB CR EQU 0DH ;CARRIAGE RETURN LF EQU 0AH ;LINE FEED SPACE EQU ' ' ;SPACE PERIOD EQU '.' ;PERIOD MASK EQU 01111111B ;SAVES 7 BITS ; -------------------------------------------------- ORG 0100H START: ; VERIFY A FILE NAME IS PRESENT IN COMMAND TAIL LDA BUFFER+0 ;LOAD CMD TAIL LNGTH CPI 2 ;AT LEAST 1 CHAR? JP CHKDRV ;YES, GO AHEAD ; LXI D,NOFILE ;LOAD ERR MSG ADDR MVI C,WRTSTR ;BDOS FUNCTION 9 CALL BDOS ;WRITE ERROR MSG JMP FINIS ;END PROGRAM CHKDRV: ; VERIFY SPECIFIED DRIVE (A:, B:, OR NONE) LDA DRIVE ;GET DRIVE # CPI 3 ;DEFAULT, A:, OR B:? JM CHKNAM ;DRIVE OK ; LXI D,INVDRV ;LOAD ERR MSG ADDR MVI C,WRTSTR ;BDOS FUNCTION 9 CALL BDOS ;WRITE ERROR MSG JMP FINIS ;END PROGRAM CHKNAM: ; VERIFY THAT FILE NAME INCLUDES NO '?' LXI H,FILNAM-1 ;LOAD ADDR OF NAME MVI B,11 ;CHK NAME(8)+EXT(3) MVI A,'?' ;SEARCH ARGUMENT LOOP1: INX H ;POINT TO NEXT CHAR CMP M ;'?' PRESENT? JZ NOAMB ;YES; PRINT ERR MSG DCR B ;DECREMENT COUNTER JNZ LOOP1 ;JMP IF MORE CHARS JMP NAMOK ;CHECK DONE AND OK NOAMB: LXI D,AMBFIL ;LOAD ERR MSG ADDR MVI C,WRTSTR ;BDOS FUNCTION 9 CALL BDOS ;WRITE ERROR MSG JMP FINIS ;END PROGRAM NAMOK: ; OPEN FILE MVI A,ZERO ;ZERO ACCUMULATOR STA EXTENT ;SET EXTENT TO ZERO STA CURREC ;SET CURR REC TO 0 LXI D,FCB ;LOAD FCB ADDR MVI C,FOPEN ;BDOS FUNCTION 15 CALL BDOS ;ATTEMPT TO OPEN CPI 0FFH ;OPEN OK? JNZ PREP ;YES ; LXI D,MISFIL ;LOAD ERR MSG ADDR MVI C,WRTSTR ;BDOS FUNCTION 9 CALL BDOS ;WRITE ERROR MSG JMP FINIS ;END PROGRAM PREP: LXI D,BUFFER ;LOAD BUFFER ADDR MVI C,SETBUF ;BDOS FUNCTION 26 CALL BDOS ;SET BUFFER ADDR MLOOP: ; MAIN PROGRAM LOOP LHLD BUFADR ;GET POINTER MOV A,L ;GET LSB OF POINTER CPI ZERO ;END OF BUFFER? JNZ GETBYT ;NO, PROCESS BYTE ; LXI H,BUFFER ;LOAD BUFFER START SHLD BUFADR ;RESET BUFFER PTR LXI D,FCB ;LOAD FCB ADDR MVI C,FREAD ;BDOS FUNCTION 20 CALL BDOS ;GET NEXT RECORD CPI ZERO ;MORE OF FILE? JNZ CLOSE ;NO, CLOSE AND END GETBYT: MOV A,M ;GET CURR BYTE ANI MASK ;MASK OFF 8TH BIT LHLD BUFADR ;LOAD POINTER INX H ;POINT TO NEXT BYTE SHLD BUFADR ;SAVE POINTER ; CHECK FOR WHITE SPACE CPI SPACE ;SPACE? JZ ENDWRD ;YES, CHECK WORD CPI CR ;CARRIAGE RETURN? JZ ENDWRD ;YES, CHECK WORD CPI LF ;LINE FEED? JZ ENDWRD ;YES, CHECK WORD CPI TAB ;TAB? JZ ENDWRD ;YES, CHECK WORD ; CHECK INDICATOR; IF NO, SET AND COUNT LDA INWORD ;GET INDICATOR CPI NO ;IS IT RESET? JNZ MLOOP ;NO, REPEAT LOOP ; LXI B,YES ;LOAD 'YES' MOV A,B ;MOVE TO ACCUM STA INWORD ;STORE IN INDICATOR ; INCREMENT COUNTER AND REPEAT LOOP LHLD NW ;LOAD COUNTER INX H ;INCREMENT SHLD NW ;SAVE COUNTER JMP MLOOP ; ENDWRD: ; AT END OF WORD; RESET INDICATOR LXI B,NO ;LOAD 'NO' MOV A,B ;MOVE TO ACCUM STA INWORD ;RESET INDICATOR JMP MLOOP ;REPEAT LOOP CLOSE: LXI D,FCB ;LOAD FCB ADDR MVI C,FCLOSE ;BDOS FUNCTION 16 CALL BDOS ;CLOSE FILE RESULT: ; DISPLAY FIRST HALF OF RESULTS MESSAGE LXI D,RESULT1 ;LOAD 1ST HALF MSG MVI C,WRTSTR ;BDOS FUNCTION 9 CALL BDOS ;WRITE 1ST HALF MSG ; DISPLAY NUMBER OF WORDS LHLD NW ;LOAD WORD COUNT LXI D,10000 CALL DIV16 ;PROCESS 1ST DIGIT LXI D,1000 CALL DIV16 ;PROCESS 2ND DIGIT LXI D,100 CALL DIV16 ;PROCESS 3RD DIGIT LXI D,10 CALL DIV16 ;PROCESS 4TH DIGIT LXI D,1 CALL DIV16 ;PROCESS 5TH DIGIT ; DISPLAY SECOND HALF OF RESULTS MESSAGE LXI D,RESULT2 ;LOAD 2ND HALF MSG MVI C,WRTSTR ;BDOS FUNCTION 9 CALL BDOS ;WRITE 2ND HALF MSG FINIS: MVI C,RESET ;BDOS FUNCTION 0 JMP BDOS ;RETURN TO SYSTEM ; -------------------------------------------------- ; SUBROUTINE TO DO 16-BIT DIVIDE ; INPUT: HL = DIVISOR (NUMBER OF WORDS) ; DE = DIVIDEND (10000, 1000, 100, 10, OR 1) ; OUTPUT: QUOTIENT ON CON:, REMAINDER IN HL DIV16: MVI B,ZERO ;INIT COUNTER DLOOP: MOV A,H ;LOAD MSB OF NW CMP D ;CMP WITH MSB OF DE JC WRITE ;PRINT RESULT JNZ CONTIN ;MSB'S EQUAL MOV A,L ;LOAD LSB CMP E ;CMP WITH LSB OF DE JC WRITE ;PRINT RESULT CONTIN: MOV A,L ;LOAD LSB SUB E ;SUBTRACT LSB'S MOV L,A ;SAVE MOV A,H ;LOAD MSB SBB D ;SUBTRACT WITH CARRY MOV H,A ;SAVE INR B ;INCREMENT COUNT JMP DLOOP ;DO ANOTHER SUBTRACT WRITE: MOV A,B ;LOAD COUNT ADI 030H ;CONVERT TO ASCII SHLD NW ;SAVE WORD COUNT MOV E,A ;STORE TO E MVI C,CONOUT ;BDOS FUNCTION 2 CALL BDOS ;PRINT DIGIT LHLD NW ;RESTORE COUNT RET ;RETURN ; -------------------------------------------------- ; CONSOLE MESSAGES NOFILE DB 'MUST SPECIFY A FILE TO COUNT',CR,LF DB '(FOR EXAMPLE: WC A:STORY.TXT)' DB CR,LF,'$' INVDRV DB 'DRIVE CODE IS NOT VALID',CR,LF DB '(MUST USE A:, B:, OR NONE.)' DB CR,LF,'$' AMBFIL DB 'AMBIGUOUS FILE NAMES NOT ALLOWED' DB CR,LF,'$' MISFIL DB 'CANNOT FIND THAT FILE' DB CR,LF,'$' RESULT1 DB 'FILE CONTAINS ','$' RESULT2 DB ' WORDS',CR,LF,'$' ; ; STORAGE AREAS BUFADR DW BUFFER+80H ;BUFFER POINTER INWORD DB NO ;YES = CURR IN WORD ;NO = BETWEEN WORDS NW DW ZERO ;WORD COUNT ; END START