实验要求: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位的,所以将地址都扩展以后存入寄存器,现在想想,是可以直接存入低位或者高位二者之一就可以了呀,否则的话,后面要取也很麻烦