; ---------------------------------------------------------------------------
; FILE: CharCount.Asm
; DATE: May 4, 2014
; ---------------------------------------------------------------------------
    OFFSET equ
    ;
    ; COM program header
    ;
    org       100h
    use16
    ;
    ; Program Entry Point
    ;
;        MOV SI,STRING

        MOV DX, OFFSET PRINT0 
        MOV AH,09H 
        INT 21H 

        MOV DX, OFFSET NEWLINE 
        MOV AH,09H 
        INT 21H 

     PR1: 
        MOV DX, OFFSET PRINT1 
        MOV AH,09H 
        INT 21H 

        MOV AH,0AH 
        MOV DX, OFFSET INMAX1  ; ag62: correct value passed for 0Ah service 
        INT 21H 

;ag62: why ask again?
;        MOV AH,0AH 
;        MOV DX,SI 
;        INT 21H 


;ag62: I think all this is for detecting if an empty string
;      was entered or length of string is more than 20 chars.
;      It can easily be done with a value of INLEN1 - it has
;      a # of characters entered. I think it counts 0Dh too,
;      so empty string will have INLEN1 set to 1. Also,
;      no need to check > 20 - because you set it as INMAX1,
;      so it is impossible to enter more than 20 chars.
; ---------------------------------------------------------
;        MOV CH,00H 
;        INC SI   
;
;     LUNG: 
;        INC SI 
;        INC CH 
;        CMP BYTE [SI], 0DH 
;        JNE LUNG 
;         
;        DEC CH 
;
;        CMP CH,00H  
;        JE ERR1 
;
;        CMP CH,14H 
;        JNBE ERR2 
;        JMP NL 

    ;ag62 - check the length

        CMP [INLEN1], 1
        JNE PR2

    ERR1: 
        MOV DX, OFFSET NEWLINE 
        MOV AH,09H 
        INT 21H 
         
        MOV DX, OFFSET ERROR1 
        MOV AH,09H 
        INT 21H 
         
        MOV DX, OFFSET NEWLINE 
        MOV AH,09H 
        INT 21H 
         
        JMP PR1  

;   ERR2: 
;        MOV SI,STRING 
;         
;        MOV DX, OFFSET NEWLINE 
;        MOV AH,09H 
;        INT 21H 
;         
;        MOV DX, OFFSET ERROR2 
;        MOV AH,09H 
;        INT 21H 
;         
;        MOV DX, OFFSET NEWLINE 
;        MOV AH,09H 
;        INT 21H 
;
;        JMP PR1 
;         
;     NL: 
;        MOV DX, OFFSET NEWLINE 
;        MOV AH,09H 
;        INT 21H  
; ---------------------------------------------------------

    PR2: 
        MOV DX, OFFSET NEWLINE   ;ag62: added a New Line here
        MOV AH,09H 
        INT 21H  

        MOV DX, OFFSET PRINT2 
        MOV AH,09H 
        INT 21H 

;ag62: I see... you read a character here differently (not with 0AH)
;      That character is returned in AL, so you need to store it, because
;      AL is usually destroyed by INT 21H
        MOV AH,1 
        INT 21H
        MOV CHAR, AL  ; ag62: save it to be loaded on lines below

        MOV DX, OFFSET NEWLINE 
        MOV AH,09H 
        INT 21H  


        MOV SI, STRING 
        MOV AL, CHAR
         
        XOR AH, AH 

     FIND: 
;        INC SI 
;        DEC CH 
        MOV BH, [SI] 
        INC SI          ;ag62: load BH and set SI to next char right away
        CMP BH, AL 
        JNE NEXT_CHAR 
                 
        INC AH 

     NEXT_CHAR: 
        CMP BH, 0DH     ; ag62: check if string ended
;        CMP CH,00H 
        JE NR_AP 
        JMP FIND 


     NR_AP: 
        ;
        ; ag62: main bug was here! AH has counted characters
        ; but it gets destroyed by next lines... need to preserve it
        ;

        PUSH AX    ;ag62: preserve AH
        MOV DX, OFFSET COUNT
        MOV AH,09H
        INT 21H
        POP AX     ;ag62: restore AH

        CMP AH, 0 
        JE PRINT_ZERO 

        SHR AX, 8 
        MOV DX, 0 
        MOV CX, 10 
        DIV CX 

        PUSH DX 
        ADD AL, '0' 
        MOV DL, AL 
        MOV AH, 2 
        ;
        ; ag62: if 1st character is '0' - do not print it
        ;
        CMP AL, '0'
        JE SKIP

        INT 21H

     SKIP:
        POP DX 
        ADD DL, '0' 
        INT 21H  
        JMP EXIT_NR 
         
     PRINT_ZERO: 
        MOV DX, OFFSET PRINTZ 
        MOV AH,09H 
        INT 21H 

     EXIT_NR: 
        MOV DX, OFFSET EXITNR 
        MOV AH,09H 
        INT 21H 
         
     EXIT: 
        MOV AH,1    ; ag62: wait for key press
        INT 21H    
         
        MOV AH,4CH 
        INT 21H 
    ;
    ; Quit to MS-DOS
    ;
    int       20h
    ;
    ; Data section
    ;
    NEWLINE DB 10,13,"$"
    INMAX1  DB 21     ; ag62: max chars for STRING
    INLEN1  DB 0      ; ag62: length of the string
    STRING  DB 21 DUP(20H)
;    CHAR    DB 2 DUP(0AH) 
    CHAR    DB 0      ; ag62: need room for only 1 character
    PRINT0  DB "Input:$" 
    PRINT1  DB "String: $" 
    PRINT2  DB "Character: $" 
    PRINTZ  DB "0 $" 
    ERROR1  DB "Error! Enter a string. $" 
;    ERROR2  DB "Error! You have entered more than 20 characters.$"  
    COUNT   DB "Output: $" 
    EXITNR  DB "$"    


