;B
     Page    66,96
     Title     Character count program
;
; --------------------  SIZE  --------------------------
;
;  Format:     SIZE
;  Purpose:    To count the number of bytes in the
;        standard input file.
;  Parameters:    None.
;  Options:    None.
;  Examples:    To count the number of characters:
;                 size <innfile
;        To count the number of lines using TRANSLIT:
;                 translit ^@n | size <infile
;        To count the number of words using TRANSLIT:
;                 translit " "@t@n @n | translit ^@n | size
;  Written:    SvJo, 1/11 1984
;  Last change:    SvJo, 14/7 1985
;
; ------------------------------------------------------
;
;    Written in assembly to implement redirection
;    under DOS 2.0
;
CR    EQU    0DH
LF    EQU    0AH
TAB    EQU    09H
FF    EQU    0CH
EOF    EQU    1AH
;
COUNT    SEGMENT
;
     ORG    100H
;
     ASSUME    CS:COUNT
;
Start:    JMP    CNT1
;
;    Stack space
;
     DW    40 DUP (0)
SStk    LABEL    WORD
;
;    Some variables
;
Char    DB    ' '
;
Wrong    DB    CR,LF
     DB    'Sorry, you need DOS 2.0 or later '
     DB    'to run this program.'
     DB    CR,LF
;
WLen    EQU    $-Wrong
;
Fulld    DB    CR,LF
     DB    'Sorry, no more room on disk. '
     DB    CR,LF
;
FLen    EQU    $-Fulld
;
CntMsg    DB    CR,LF
     DB    'Size = '
CntBeg    DB    0,0,0,0,0,0
CntEnd    DB    0
CntDif    EQU    CntEnd-CntBeg
     DB    CR,LF
;
CntLen    EQU    $-CntMsg
;
CNT1:    MOV    AX,CS
     MOV    DS,AX
     MOV    ES,AX
     MOV    SS,AX
;
     ASSUME    DS: COUNT
     ASSUME    ES: COUNT
     ASSUME    SS: COUNT
;
     MOV    SP,Offset SStk
;
;    Check that operating system version is compatible
;
     MOV    AH,30H
     INT    21H
     CMP    AL,2         ;Version must be at least 2.0
     JGE    CNT2
;
;    Wrong version DOS, send message and abort
;
     MOV    AH,40H
     MOV    BX,02H         ;Standard error device
     MOV    CX,WLen
     MOV    DX,Offset Wrong
     INT    21H
;
     MOV    AX,0
     INT     21H           ;Abort
;
;    Clear ASCII accumulator
;
CNT2:    MOV    AL,0
    MOV    DI,Offset CntBeg
    MOV    CX,CntDif+1
    REP    STOSB
;
CNT3:    CALL    GETC
    TEST    AH,AH
    JNZ    CNT10
    TEST    AL,AL
    JZ    CNT3
;
;    Legal character, increment in ASCII
;
    MOV    BX,Offset CntEnd
    MOV    AL,[BX]
    DEC    BX
    MOV    CX,CntDif
    MOV    AH,[BX]
    ADD    AL,1
;
CNT4:    AAA
    MOV    [BX+1],AL
    MOV    AL,AH
    JNB    CNT3
    DEC    BX
    MOV    AH,[BX]
    JMP    CNT4
;
;    Make ASCII and eliminate leading zeros
;
CNT10:    MOV    BX,Offset CntBeg
    MOV    AH,' '
    MOV    CX,CntDif
;
CNT11:    MOV    AL,[BX]
    OR    AL,AH
    CMP    AL,AH
    JE    CNT12
    MOV    AH,'0'
    OR    AL,AH
CNT12:    MOV    [BX],AL
    INC    BX
    LOOP    CNT11
;
    OR    BYTE PTR [BX],'0'
;
;    Send count to standard output
;
     MOV    CX,CntLen
    MOV    AH,40H         ;Write
     MOV    BX,01H         ;Standard output
     MOV    DX,Offset CntMsg
     PUSH    CX
     INT    21H
     POP    CX
     CMP    AX,CX         ;Equal if OK
     JE    CNT25
;
    MOV    AH,40H
     MOV    BX,02H         ;Standard error device
     MOV    CX,FLen
     MOV    DX,Offset Fulld
     INT    21H
;
     MOV    AX,0
     INT     21H           ;Abort
;
CNT25:    CALL    CLOSE         ;Close file
;
     MOV    AX,0
     INT     21H           ;Abort
;
;    Get a character from standard input
;    Return char. in AL, EOF in AH
;
GETC:    MOV    AH,3FH         ;Read
     MOV    BX,0         ;Standard input
     MOV    DX,Offset Char
     MOV    CX,1         ;One byte
     INT    21H
     MOV    AH,0FFH         ;Check for EOF
     AND    AL,AL
     JZ    GETC2
     CMP    Char,EOF
     JE    GETC2
     INC    AH
     CMP    Char,LF         ;LF and not EOF?
     JE    GETC         ;Then get next char
GETC2:    MOV    AL,Char
     RET
;
;    Close standard output
;
CLOSE:    MOV    AH,3EH         ;Close
     MOV    BX,01H         ;Std. out
     INT    21H
     RET
;
COUNT    ENDS
;
     END    Start