汇编 统计字符个数

实验四要做的是:分类统计字符的个数
实验要求:1.接收从用户键入的一串字符(不超过80,用回车结束)。2.按字母,数字,其他字符分类进行计数,然后将结果存入以letter,digit,和other为名的存储单元中。


模块1 main  为总控模块
输入:从键盘输入一串字符
输出:显示每类数据的数目
功能:根据输入的字符,若某类数据出现一次则其所对应的存储单元中的数增加1.可以将数目存到某一寄存器中,将该数据存入存储单元中


模块2 input 为输入模块
输入:从键盘输入一串字符串
输出:输出到一个字符串数组中
功能:调用子模块crlf实现回车换行的功能


模块3 count 为计数模块
输入:从input模块中取得一个字符
输出:将各种字符的数目存入相应的存储单元中
功能:算法是,从字符串数组中取出一个字符,判断属于哪种类型,若属于letter,则letter相应
      的寄存器中加1,同理别的也是这样(此处需要几个分支),判断是否结束,若结束,则该 
      字符串结束,将对于的寄存器中的数目移到相应的存储单元中。


模块4:output 从存储单元中取出数目输出
输入:存储单元取出16进制的数目
输出:将数目转换成10进制数字输出
功能:将存储单元中的数据转换成10进制后输出到屏幕上,调用crlf子模块,实现换行的功能




模块5:crlf 回车换行的功能



自己写的代码:

data segment        ;定义数据段
input1     db        80,?,80 dup(?) ;定义输入字符串的缓冲区,数目最大为80
print        db        'Input the sentence:','$'  ;提示输入要计数的句子
mes1         db        'The number of letter is','$' ;提示输出letter的数目
mes2         db        'The number of digit is','$'  ;提示输出digit的数目
mes3         db        'The number of other is','$'  ;提示输出other的数目
crlf1         db        13,10,'$'                   ;回车换行
letter       dw        ?                             ;定义一个存储空间来存letter数目
digit        dw        ?                             ;定义一个存储空间来存储digit数目
other        dw        ?                             ;定义一个存储空间来存储other数目
data ends
;***********************************************************************
code segment        ;定义程序段
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
main proc  far
     assume cs:code,ds:data
start:
;建立一个栈用于返回
push ds
sub  ax,ax
push ax
;将ds设为当前的数据段


mov ax,data    
mov ds,ax


sub ax,ax       ;初始化letter,digit,other 
mov letter,ax


mov digit,ax


mov other,ax


lea dx,print       ;打印输入数据提示符
mov ah,09h
int 21h


call input          ;调用input子模块来输入字符串
call count          ;调用count子模块来处理字符串
call output         ;调用output子模块来输出结果


main endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
input proc near


lea dx,input1       ;从缓冲区输入字符串
mov ax,0ah
int 21h


mov cl,[input1+2]   ;获得输入的字符串的长度
cbw


mov SI,input1+3   ;获得第一个字符的位置


ret                 ;返回


input endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
count proc near
begin :
mov bx,[SI]      ;获得SI所指的位置的字符


c0:
cmp bx,'0'
jnb c1 
jb  c7  ;若小于‘0’则为other


c1:
cmp bx,'9'
jna c8 ;是数字的情况
ja  c2  ;否则判断是否是letter


c2:
cmp bx,'A'
jnb c3
jb  c7  ;若是小于‘A’的则为other


c3:
cmp bx,'Z'
jna c6  ;若不大于则是letter
ja  c4  ;若大于则判断是否是小写


c4:
cmp bx,'a'
jnb c6    ;若是不小于则为letter
jb  c7    ;若小于则为other


c5:
cmp bx,'z'
jna c6   ;不大于则是letter
ja c7    ;若大于‘z’则是其他的字符


c6:
lea ax,letter
inc ax
mov letter,ax
cmp cx,0
jz output ;若cx为0则已经处理完毕进行输出
jnz rebegin ;否则到rebegin


c7:       ;other的情况
lea ax,other
inc ax
mov other,ax
cmp cx,0
jz output ;若cx为0则已经处理完毕进行输出
jnz rebegin ;否则到rebegin


c8:         ;digit的情况
lea ax,digit
inc ax
mov digit,ax
cmp cx,0
jz output ;若cx为0则已经处理完毕进行输出
jnz rebegin ;否则到rebegin


rebegin:
inc SI  ;取下一个
jmp begin


ret
count endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
output proc near


lea dx,mes1        ;显示打印letter数目的提示符
mov ax,09h
int 21h


lea dx,letter      ;将letter数目打印
int 21h


call crlf          ;回车换行


lea dx,mes2        ;显示打印digit数目的提示符
int 21h


lea dx,digit       ;将digit数目进行打印
int 21h


call crlf          ;回车换行


lea dx,mes3        ;显示打印other数目的提示符
int 21h


lea dx,other       ;将other数目进行打印  
int 21h


call crlf          ;回车换行


mov ah,4ch         ;打印完毕退出
int 21h 


ret
output endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
crlf   proc near   ;打印回车换行
mov ah,09h
lea dx,crlf1
int 21h
ret
crlf endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
code ends
     end start



代码编译没有任何错误,但是,在运行时就会出现一个奇怪的对话框:




给老师发了一个邮件,很开心,老师很快就给回复了,

   1.地址与单元内容的助记符的使用不对;

    2.数据定义有问题,我们的字符都是用字节定义的;

以下是修改过的代码:


data segment        ;定义数据段
input1     db        80,?,80 dup(?) ;定义输入字符串的缓冲区,数目最大为80
print        db        'Input the sentence:  ','$'  ;提示输入要计数的句子
mes1         db        'The number of letter is  ','$' ;提示输出letter的数目
mes2         db        'The number of digit is  ','$'  ;提示输出digit的数目
mes3         db        'The number of other is  ','$'  ;提示输出other的数目
crlf1         db        13,10,'$'                   ;回车换行
letter       db        ?                 ;定义一个存储空间来存letter数目
digit        db        ?                 ;定义一个存储空间来存储digit数目
other        db        ?                 ;定义一个存储空间来存储other数目
data ends                                 ;sdfffg’’’’
;***********************************************************************
code segment        ;定义程序段
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
main proc  far
       assume cs:code,ds:data
start:
;建立一个栈用于返回
push ds
sub  ax,ax
push ax
;将ds设为当前的数据段


mov ax,data    
mov ds,ax


sub ax,ax       ;初始化letter,digit,other 
mov letter,al
mov digit,al
mov other,al
lea dx,print       ;打印输入数据提示符
mov ah,09h
int 21h
call input          ;调用input子模块来输入字符串
call crlf
call count          ;调用count子模块来处理字符串
;call output         ;调用output子模块来输出结果
mov ah,4ch         ;
int 21h 
main endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
input proc near
lea dx,input1       ;从缓冲区输入字符串
mov ah,0ah
int 21h
mov cl,[input1+1]   ;获得输入的字符串的长度
lea SI,input1+2   ;获得第一个字符的位置
ret                 ;返回
input endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
count proc near
begin :
mov bl,[SI]      ;获得SI所指的位置的字符
c0:
cmp bl,'0'
jnb c1 
jb  c7  ;若小于‘0’则为other
c1:
cmp bl,'9'
jna c8 ;是数字的情况
ja  c2  ;否则判断是否是letter
c2:
cmp bl,'A'
jnb c3
jb  c7  ;若是小于‘A’的则为other
c3:
cmp bl,'Z'
jna c6  ;若不大于则是letter
ja  c4  ;若大于则判断是否是小写
c4:
cmp bl,'a'
jnb c6    ;若是不小于则为letter
jb  c7    ;若小于则为other
c5:
cmp bl,'z'
jna c6   ;不大于则是letter
ja c7    ;若大于‘z’则是其他的字符
c6:
mov al,letter
inc al
dec cl
mov letter,al
cmp cl,0
jz  output1 ;若cx为0则已经处理完毕进行输出
jnz rebegin ;否则到rebegin
c7:       ;other的情况
mov al,other
inc al
dec cl
mov other,al
cmp cl,0
jz output1 ;若cx为0则已经处理完毕进行输出
jnz rebegin ;否则到rebegin
c8:         ;digit的情况
mov al,digit
inc al
dec cl
mov digit,al
cmp cl,0
jz output1 ;若cx为0则已经处理完毕进行输出
jnz rebegin ;否则到rebegin


rebegin:
inc SI  ;取下一个
jmp begin
output1:
call output
ret
count endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
output proc near
lea dx,mes1        ;显示打印letter数目的提示符
mov ah,09h
int 21h
mov dl,letter      ;将letter数目打印
or dl,30h
mov ah,02h
int 21h
                  call crlf


lea dx,mes2        ;显示打印digit数目的提示符
mov ah,09h
int 21h
mov dl,digit       ;将digit数目进行打印
                  or  dl,30h
mov ah,02h
int 21h
                  call crlf
                 
mov ah,09h
lea dx,mes3        ;显示打印other数目的提示符
int 21h
                  mov ah,02h
mov dl,other       ;将other数目进行打印 
                  or dl,30h 
int 21h
call crlf          ;回车换行
ret
output endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
crlf   proc near   ;打印回车换行
mov ah,09h
lea dx,crlf1
int 21h
ret
crlf endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

code ends

     end start


通过对比发现主要问题果然就是老师说的几个问题:

1.定义时我使用了dw的定义方式,当时的想法是一个整形的数字要占用4个字节,所以就定义了一个dw的类型 ,现在想想,一个字节就可以记录句子中字符的数目

2.对于输入的那个字符区的定义不甚了解,开始的做法就是老师修改的那样,然后出了错后想,定义的字符应该也占一个位置吧,就变成了上面的程序那个样子。。。。

3.对于寄存器的了解不够,每个寄存器是16位的,数字定义成字节类型的话,只需要低位或者高位就可以。

刚开始时,地址觉得是8位的,所以将地址都扩展以后存入寄存器,现在想想,是可以直接存入低位或者高位二者之一就可以了呀,否则的话,后面要取也很麻烦



     
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值