汇编实验:分类统计字符个数

 2.3  分类统计字符个数

     1.题目:分类统计字符个数

  2.实验要求:

    程序接收用户键入的一行字符(字符个数不超过80个,该字符串用回车符结束),并按字母,数字及其他字符分类计数,然后将结果存入以letter,digit和other为名的存储单元中。

 

datarea   segment
  letter1   db   ?
  digit1    db   ?
  other1    db   ?
  string   label  byte
           max db 80 
           act db ?  
           str db 80 dup(?)
print   db  13,10,'Please enter the string:','$'
mess1   db  13,10, 'The total number of letter : ','$'
mess2   db  13,10,'The total number of digit  : ','$'
mess3   db  13,10,'The total number of other character : ','$'
datarea   ends
prognam  segment
      assume  cs:prognam,ds:datarea
start: push  ds
       sub  ax,ax
       push  ax
       mov   ax,datarea
       mov   ds,ax
       mov   es,ax
       mov   letter1,0
       mov   digit1,0
       mov   other1,0
       lea   dx,print
       mov   ah,09h  
       int   21h
       lea   dx,string
       mov   ah,0ah
       int   21h
       sub   ch,ch
       mov   cl,[string+1]
       lea   si,string+2
digitseg: 
       mov   al,[si]
       cmp   al,'0'
       jb    otherseg     ;小于0为其他,0到9为数字
       cmp   al,'9'
       ja    letter1seg    
       inc   digit1
       jmp   loop1
letter1seg: 
       cmp   al,'A'       ;接上面,判断9之后,大于9,小于A为其他,A到Z为字母
       jb    otherseg   ;jb  cf=1 (无符号数溢出)则转移,ja  cf与zf=1则转移
       cmp   al,'Z'
       ja    letter2seg 
       inc   letter1
       jmp   loop1  
letter2seg:  
       cmp   al,'a'      ;接上面,判断Z之后,大于Z,小于a为其他,a到z为字母
       jb    otherseg
       cmp   al,'z'
       ja    otherseg
       inc   letter1
       jmp   loop1
otherseg: 
       inc   other1
loop1:  
       inc   si
       dec   cl
       cmp   cl,0
       jz    print1 
       jne   digitseg    ;重复分类过程  
print1:   
       lea   dx,mess1
       mov   ah,09h
       int   21h
       mov   al,letter1
       call  disp
       lea   dx, mess2
       mov   ah,09h
       int   21h
       mov   al,digit1
       call  disp
       lea   dx, mess3
       mov   ah,09h
       int   21h
       mov   al,other1
       call  disp
exit:
       mov   ah, 4ch
       int  21h
disp:                 ;十进制数形式显示AL中的内容.
       mov  ah, 0
       mov  bl, 10
       div  bl        ;div 无符号:div src 16位操作:商ax=(dx,ax)/src,余数dx
       add  al, 30h    ;比如说al=15h,即21,表示letter数量,然后,这个过程就是,ax=0015h(21),除以bl,bl值为10
       mov  dl, al      ;则除完了的结果为2余1,则ah=01,al=02,即ax=0102h;,那么al+30h即为表示该数字的ASCII码值,因为0的ASCII值为30h
       mov  bh, ah       ;则ax=0132h,dl=32,bh=01;
       mov  ah, 02h      ;显示输出dx,则显示32码对应的数字,2
       int  21h           
       mov  al, bh        ;把01给al,然后算出ASCII码,然后给dx,然后显示
       add  al, 30h
       mov  dl, al        ;除数B有 8位和16位两种,保存在一个reg寄存器里 或是内存单元中。
 
                          ;被除数A 默认存放在AX中(16位以内) 或 AX和DX中(32位,DX存放高16位,AX存放低16位)
 
                          ;结果: 如果除数B是8位,那么除法的结果AL保存商,AH保存余数,
                          ;如果除数B是16位,那么除法的结果 AX保存商,DX保存余数。
       mov  ah, 02h
       int  21h     
       ret
;---------------------------------------
;****************************************       
prognam   ends
       end   start

运行结果:

(1)这个实验我做了额外的16进制数转换成10进制数输出,在不进入debug运行的情况下,显示出的结果更加规范美观。

  修改前,16进制输出:


修改之后,10进制输出:

汇编实验:分类统计字符个数_第1张图片

(2)在debug运行结果:

反汇编结束后,我们利用g0b命令跳到程序执行前,然后利用d0命令显示寄存器内容,其中蓝色标记代表存入letter,digit,other的字符数量,接着红色的标记代表为输入字符申请的空间,最多80个字符(16进制为50),接着黄色标记代表输入的字符总数,紫色的标记代表存入的80个字符,显示为对应字符的ASCII码,后续即为程序的输出显示语句之类的其他ASCII码。

汇编实验:分类统计字符个数_第2张图片

利用g9b命令跳到程序输入字符,显示的阶段,然后利用d0命令显示寄存器内容,输入字符之后,统计字符结果保存到相应位置,我们可以清晰的看到执行的结果。其中输出是用10进制表示,而存的时候显示为16进制,我输入字符之后,letter有16个,对应第一个位置存16进制10,digit有9个,对应显示16进制09,other有10个,对应显示16进制0a;黄色标记部分显示字符总数35,16进制显示23,接着紫色部分显示的是输入字符的ASCII码。

汇编实验:分类统计字符个数_第3张图片

问题及收获

本次实验自己动手做实验教材2.3,刚开始看到题目感觉利用上一次做的实验的思想就可以实现,如何输入,如何将其保存,然后再一个个字符拿出来比较属于哪一类,然后将该类别数量增一。可以利用分支程序实现。最后我采用16进制转换成10进制输出结果,这样更加直观。总体来说,遇到的问题没有很多,其他一些小问题,稍微注意一点就可以了。就是我想着要将其转换为10进制数字显示时,有点麻烦,我找了好多资料,然后对比分析,最后自己写出了相应的转换代码:

汇编实验:分类统计字符个数_第4张图片

最开始就是卡在div这个操作这里,因为我以为无论操作数有多少位,余数都存在dx中了,然而如果除数是8位,那么除法的结果AL保存商,AH保存余数,如果除数是16位,除法的结果才是 AX保存商,DX保存余数。这样搞明白之后,把相应的数字转换成ASCII码,以字符形式分高位,地位输出。



你可能感兴趣的:(汇编)