DATAS SEGMENT 
STRING1 DB"Please input a string:$"   ;输入提示信息 
STRING2 DB'letters:$ '                ;各类字符提示信息 
STRING3 DB'digits:$' 
STRING4 DB'others:$'
STRING db 80,?,80 dup(?)               ;原字符串 
LETTER db 80 dup(?),'$'                ;字母 
DIGIT db 80 dup(?),'$'                 ;数字 
OTHERS db 80 dup(?),'$'                ;其他
DATAS ENDS
STACKS SEGMENT 
STACKS ENDS  
CODES SEGMENT 
ASSUME CS:CODES,DS:DATAS,SS:STACKS 
START: 
MOV AX,DATAS 
MOV DS,AX
LEA DX,STRING1 ;显示输入提示信息Please input a string 
MOV AH,09H 
INT 21H              
MOV AH,0AH
lea DX,STRING
INT 21H             ;这是我改写的

           
MOV BX,0            ;原始字符串位置
MOV SI,1            ;letter
MOV DI,1            ;digit
MOV BP,1            ;others
MOV CH,0
    MOV CL,[STRING+1] ;设置循环次数足够大 
DIGITS:
   
MOV AL,STRING[BX]   ;把string空间的字符给al寄存器
 
    CMP AL,0DH ;若输入回车符则结束 
JZ OVER2            ;若AL中为0DH 即回车符则跳转
CMP AL,'0' ;若<0,OTHER 
JB OTHER            ;JB小于则跳转
CMP AL,'9' ;若>9),跳转letter1比较 
JA  LETTERS1         
MOV DIGIT[DI],AL    ;若>0且<9则把此字符送到digit数组空间内,数组下标为DI
INC DI        ;数字(下标)++ 
JMP OVER    ;比较结束 
LETTERS1:
    CMP AL,'A'         
JB OTHER            ;若<A,跳转OTHER
CMP AL,'Z'
JA LETTERS2         ;若>Z,跳转LETTERS2                            
MOV LETTER[SI],AL   ;若>A且<Z则把此字符送入LETTER数组空间内,数组下标SI
INC SI        ;字母++ 
JMP OVER    ;比较结束  
LETTERS2:    
    CMP AL,'a'          ;若<a,OTHER     
JB OTHER                                       
CMP AL,'z' ;若>z,OTHER      
JA OTHER 
MOV LETTER[SI],AL   ;若>a且<z则把此字符送入LETTER数组空间内,数组下标SI
INC SI        ;字母++ 
JMP OVER ;比较结束 

OTHER:
MOV OTHERS[BP],AL   ;把AL内容送入OTHERS数组空间内,数组下标BP
INC BP           ;OTHERS++
JMP OVER    ;比较结束 
OVER:   LOOP DIGITS     ;循环,输入下一字符 
OVER2:
CALL ENDLINE        ;回车换行 
LEA DX,STRING2 ;字符串的输出STRING2
MOV AH,09H 
    INT 21H 
XOR AX,AX           ;AX清零,CF也清零
DEC SI              ;si减一
MOV AX,SI           ;将统计的数字送AX
MOV SI,0
MOV LETTER[SI],AL
CALL DISPLAY ;调用输出两位数字的子程序
MOV SI,1               
LEA DX,LETTER+1
MOV AH,09
INT 21H 
CALL ENDLINE
LEA DX,STRING3 ;字符串的输出STRING3
MOV AH,09H 
INT 21H 
XOR AX,AX
DEC DI
MOV AX,DI           ;将统计的数字送AX
MOV SI,0
MOV DIGIT[SI],AL  
CALL DISPLAY    ;调用输出两位数字的子程序 
MOV DI,1           
LEA DX,DIGIT+1
MOV AH,09
INT 21H
CALL ENDLINE 
LEA DX,STRING4 ;字符串的输出STRING4 
MOV AH,09H 
INT 21H 
XOR AX,AX
DEC BP 
MOV AX,BP           ;将统计的数字送AX 
MOV BP,0
MOV DS:OTHERS[BP],AL
CALL DISPLAY ;调用输出两位数字的子程序 
MOV BP,1           
LEA DX,OTHERS+1
MOV AH,09
INT 21H
MOV AH,4CH 
INT 21H             ;结束语句
ENDLINE PROC NEAR ;控制输出格式,输出回车换行子程序 
MOV AH,02H 
MOV DL,0AH 
INT 21H ;输出换行符 
MOV AH,02H 
MOV DL,0DH 
INT 21H ;输出回车符 
RET 
ENDLINE ENDP 
DISPLAY PROC NEAR ;输出两位数字的子程序(输出两位数字为十进制) 
MOV BL,10 
DIV BL ;AX/BL,AL=商,AH=余数 
PUSH AX ;保存AX 中的信息 
MOV DL,AL 
ADD DL,30H   
    MOV AH,02H 
INT 21H ;输出十位数 
POP AX ;出栈送AX 
MOV DL,AH 
ADD DL,30H

MOV AH,02H 
INT 21H ;输出个位数 
RET 
DISPLAY ENDP 
CODES ENDS 
END START