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

来源:互联网 发布:我的第一本编程书 编辑:程序博客网 时间:2024/04/27 03:59


;************************************************************实验代码

datarea         segment

 

      mess1           db          'Please enter character string : ',13,10,'$'

      mess2      db       'The number of letter is ','$'

      mess3      db       'The number of digit is ','$' 

      mess4      db       'The number of other is ','$' 

      

      cstring          label      byte

        max         db         80

        act           db         ?

        cstr          db         80D dup(?)

       

      letter             db         0

      digit              db         0

      other            db         0

 

      ;number       db         '10','$','11','$','12','$','13','$','14','$','15','$'

      number        db         41h,42h,43h,44h,45h,46h,'$'

      

 

datarea         ends

;************************************************************

 

;************************************************************

prognam      segment

 

main      procfar

      assume  ds:datarea,cs:prognam

;--------------------------------------------------------------

      start:

             push      ds

             sub        ax,ax

             push      ax

 

             mov      ax,datarea

             mov      ds,ax

 

             lea         dx,mess1             ;显示字符串

             mov      ah,09h

             int         21h

 

             sub        ax,ax                           ;将计数的存储单元初始为0

             mov      letter,al

             mov      digit,al

             mov      other,al

 

 

             lea         dx,cstring                    ;键入一行字符

             mov      ah,0Ah

             int         21h

 

             ;需要换行吗?

 

             mov      cl,[cstring+1]        ;分类计数的次数

             lea         si,cstring+2          ;初始指针指向

             

             call newline

;----------------------------------------------------------------

      begin:

             mov      bl,[si]

;------------------------------------

      cmp1:                                              ;将字符分类

             cmp       bl,'0'

             jnb        cmp2

             jb          others

 

      cmp2:

             cmp       bl,'9'

             jna         digits

             ja           cmp3

 

      cmp3:

             cmp       bl,'A'

             jnb        cmp4

             jb          others

 

      cmp4:

             cmp       bl,'Z'

             jna         letters

             ja           cmp5

 

      cmp5:

             cmp       bl,'a'

             jnb        cmp6

             jb          others

 

      cmp6:

             cmp       bl,'z'

             jna         letters

             ja           others

;-----------------------------------

      letters:                                      ;记录结果

             mov      al,letter

             inc         al

             dec        cl

             mov      letter,al

             cmp       cl,0

             jz           print

             jnz         again

 

      digits:

             mov      al,digit

             inc         al

             dec        cl

             mov      digit,al

             cmp       cl,0

             jz           print

             jnz         again

 

      others:

             mov      al,other

             inc         al

             dec        cl

             mov      other,al

             cmp       cl,0

             jz           print

             jnz         again

;------------------------------------

      again:

             inc         si

             jmp       begin

;------------------------------------

      print:                                               ;打印结果

             lea         dx,mess2

             mov      ah,09h

             int         21h

 

             mov      dl,letter

             cmp       dl,10D

             jnb        conout

 

             or          dl,30h

             mov      ah,02h

             int         21h

             call newline

             jmp       next1

      

      conout:

             sub        dl,10D

             mov      ah,0

             mov      al,dl

             lea         si,number

             ;mul       al,2

            ;add       al,dl              ;*3

             add       si,ax

             mov      dl,[si]

             mov      ah,02h

             int         21h

             call newline

      ;--------------------     

      next1:

             lea         dx,mess3

             mov      ah,09h

             int         21h

 

             mov      dl,digit   

             cmp       dl,10D

             jnb        conout2

 

             or          dl,30h

             mov      ah,02h

             int         21h

             call newline

             jmp       next2

 

      conout2:

             sub        dl,10D

             mov      ah,0

             mov      al,dl

             lea         si,number

             ;mul       al,2

             ;add       al,dl

             add       si,ax

             mov      dl,[si]

             mov      ah,02h

             int         21h

             call newline

      ;----------------------

      next2:

             lea         dx,mess4

             mov      ah,09h

             int         21h

 

             mov      dl,other  

             cmp       dl,10D

             jnb        conout3

 

             or          dl,30h

             mov      ah,02h

             int         21h

             call newline

             jmp       over

 

      conout3:

             sub        dl,10D

             mov      ah,0

             mov      al,dl

             lea         si,number

             ;mul       al,2

             ;add       al,dl       

             add       si,ax

             mov      dl,[si]

             mov      ah,02h

             int         21h

             call newline

             

      over:

             mov    ah,4ch        ;带返回码终止

             int    21h

 

main      endp

;----------********************------------------

newline         procnear      ;打印空格、换行

             mov      dl,13                                  

             mov      ah,02h

             int         21h

 

             mov      dl,10

             mov      ah,02h

             int         21h

             

             ret

newline         endp

;----------********************------------------

 

;---------------------------------------------------------

prognam      ends

;*********************************************************

             end       start






编译及运行结果

 

 

 

 

 

问题及收获

      这次实验遇到了许多问题,首先出现最多的问题就是输出乱码和不正确的结果,由于编译的过程中没有报错,我也不是非常熟练debug,所以遇到这些问题很麻烦。另一个问题就是出现语法报错和警告。

      首先先总结一下出现的语法错误。本实验除去数据段、代码段的初始化和附加段(实现空格和换行),主要分为三个部分,第一个是对键入字符的选择判断,第二个是记录键入字符分类的结果,第三是输出字符分类的结果。

      第一个通过ASCII码比较实现,将属于0-9ASCII值的字符记入digit中,将A-Za-zASCII值的字符记入letter中,将不属于之前两部分的字符记入other中。

      第二个的内容是根据跳转入口,将对应的类的计数值增一,循环次数减一,再判断是否继续循环还是输出记录结果。

      第三个是根据02功能调用,输出字符仅限dl寄存器。而将记录的次数转换为ASCII值有0-9的局限。原本我试图将‘10’‘11’‘12’‘13’‘14’‘15’的值存入数据段,再利用09功能调用实现输出,但是出现了乱码和错误的结果。最后我利用数组和02功能调用实现了大于9的结果输出。

      

      在实验过程中出现的问题有must be index or base register,网上给出的结果是:

 1、使用寄存器间接寻址时,只可以使用 BX, BP, SI, DI 这四个寄存器中的一个,不可以使用其它寄存器。
  2、提示的意思是(方括号里)必须是变址(index,指SI, DI)或基址(base,指BX,BP)寄存器。

      根据编译给出的错误,对应的代码是mov dx,[si+ax],这里ax存放的指针偏移量,根据上面的提示,方括号中不能出现ax寄存器,所以修改的结果是:

add si,ax

movdx,[si]

       后来又在网上查了一下,在inter指令集中lea指令可以在方括号[ ]中使用其他的寄存器,而这里是mov指令。根据网上的说法,lea指令的功能很强大:

1、LEA指令具有单时钟周期,执行效率很高;2、它是CPU地址生成单元参与运算的,而不是ALU参与运算的,所以在流水线上不会与上下文的算术逻辑指令产生流水相关;3、INTEL指令集中不存在很多RISC机器所具有的三操作数算术运算指令,比如像ARM的"add r0,r1,r2",而LEA指令恰好提供了同样的功能,以模拟“三元算术逻辑指令”,即在方括号[ ]中便可以进行算术运算。


      出现乱码的原因主要是因为在数据段定义的字符串,结尾没有用‘$’作为终结,而我之前想通过;number            db         '10','$','11','$','12','$','13','$','14','$','15','$' 实现字符串的输出并终结,但出现了很奇怪的问题,至今没有解决。

 

leamov的区别

另外在编译过程中出现的警告,问题是leamov的混用,第一个地方是

lea         si,cstring+2          ;初始指针指向     一开始我使用的mov,出现了警告

如果执意要用mov替代,mov si,offset cstring+2


      后来问过老师才知道09功能调用在数据段的字符串定义只能使用一个 '$',然后我又想了想,如果实在要将'10','11'……'15'输出,可以这样定义数据段的字符串:

                           number   db    '10 ','11 ','12 ','13 ','14 ','15 ','$'

     这里可以看出,在单引号中的'10'等数中,后面都有一个空格,那么可以使用  repz  movsb 逐个字节读入,遇到空格就停止,这样就可以实现10这个字符串读出的功能了,(当然,同样需要定义指针指向相应的首位置)。

1 0