汇编语言程序设计:模块化程序设计 输入字符类型统计的设计与调试

任务要求

编写一个汇编程序,使得从键盘上输入十个以内的字符,以输入回车结束,然后按数字、字母和其它符号三类统计各自的个数,统计结果分别保存在BL(保存小写字母的个数)、BH(保存大写字母的个数)、DH(保存数字的个数)和DL(保存其他字符的个数)四个寄存器中。

正确代码

DATA SEGMENT
    S_OUT DB 'Please enter a string less than 10 characters:$'
    S_INT DB 11, ?, 11 DUP(0)
    COUNT EQU $-S_INT 
DATA ENDS

STACK SEGMENT STACK
    DB 100 DUP(?)
STACK ENDS

CODE SEGMENT 
    ASSUME DS:DATA, CS:CODE, SS:STACK
    START:
          MOV AX, DATA
          MOV DS,AX

          MOV AH,09H
          LEA DX, S_OUT
          INT 21H

          MOV AH, 0AH
          LEA DX, S_INT
          INT 21H

          LEA SI, S_INT+2
          MOV CX, COUNT-3   ;防止地址出现遍历次数过多的情况
         
          MOV BX, 0
          MOV DX, 0
          CALL ENUMERATE
          
          MOV AH, 4CH
          INT 21H

ENUMERATE PROC
  AGAIN:  MOV AL, [SI]
          CMP AL, 'A'
          JB NEXT
          CMP AL, 'Z'
          JA NEXT1
          ADD BH, 1
          INC SI
          LOOP AGAIN
          RET

  NEXT:   CMP AL, '0'
          JB DONE
          CMP AL, '9'
          JA DONE
          ADD DH, 1
          INC SI
          LOOP AGAIN
          RET

  DONE:   ADD DL, 1
          INC SI
          LOOP AGAIN 
          RET
          

  NEXT1:  CMP AL, 'a'
          JB DONE
          CMP AL, 'z'
          JA DONE
          ADD BL, 1
          INC SI
          LOOP AGAIN
          RET

ENUMERATE ENDP
        
          
CODE ENDS
    END START

执行结果

从执行结果可以看到,程序执行完毕后,数字存入了要求的寄存器中

心路历程 

 来吧分析

第一个要求是从键盘上输入十个以内的字符,以输入回车结束,这个其实好实现,关键在回车结束而不是以字符$结束,(LEA CRLF)还有要求输入十个以内的字符,这样的话需要限定存储单元的长度为10,并且设置超出范围的报错(用C++先预演下)提示信息为:请输入十个以内的字符,请重新输入:,需要有提示后返回主程序继续执行,继续判断的功能

按数字,字母和其他三类统计各自的个数,BL(存小写字母的个数,小写字母其实是61-7A),BH(存大写字母个数,大写字母是41-5A),DH(保存数字的个数,30-39),DL(保存其他字符的个数,不是大小写字母,数字,剩下的就是其他字符)

注意MOV指令中寄存器的匹配问题

那,题目解析完了,基本的判断逻辑架构也有了,接下来解决下具体的实现问题

本来是用子程序的,写着写着成分支结构了

DATA SEGMENT
    S_OUT DB '请输入长度小于十的字符串:$'
    S_INT DB 10, ?, DUP(10)
    COUNT EQU $-S_INT
DATA ENDS

STACK SEGMENT STACK
    DB 200 DUP(?)
STACK ENDS

CODE SEGMENT 
    ASSUME DS:DATA, CS:CODE, SS:STACK
    START MOV AX,DATA
          MOV DS,AX

          MOV AH,09H
          LEA DX,S_OUT
          INT 21H

          MOV AH, 0AH
          LEA DX,S_INT
          INT 21H

          MOV [SI],DX
          MOV CX, COUNT
          MOV BX, 0
          MOV DX, 0

  AGAIN:  MOV AL,[SI]
          CMP AL,'A'
          JL NEXT
          CMP AL,'Z'
          JB NEXT1
          ADD BH, 1
          INC SI
          LOOP AGAIN

  NEXT:   CMP AL, '0'
          JL DONE
          CMP AL, '9'
          JB DONE
          ADD DH, 1
          INC SI
          LOOP AGAIN

  DONE:   ADD DL, 1
          INC SI
          LOOP AGAIN 

  NEXT1:  CMP AL, 'a'
          JL DONE
          CMP AL, 'z'
          JB DONE
          ADD BL, 1
          INC SI
          LOOP AGAIN
          
CODE ENDS
    END START

第二版代码

改了第一版的报错,但产生了卡死,估计是CX循环的问题

DATA SEGMENT
    S_OUT DB 'Enter a string less than 10 characters:$'
    S_INT DB 10, ?, 10 DUP(10)
    COUNT EQU $-S_INT
DATA ENDS

STACK SEGMENT STACK
    DB 100 DUP(?)
STACK ENDS

CODE SEGMENT 
    ASSUME DS:DATA, CS:CODE, SS:STACK
    START:
	      MOV AX, DATA
          MOV DS,AX

          MOV AH,09H
          LEA DX,S_OUT
          INT 21H

          MOV AH, 0AH
          LEA DX,S_INT
          INT 21H

          MOV [SI],DX
          MOV CX, COUNT
          MOV BX, 0
          MOV DX, 0

  AGAIN:  MOV AL,[SI]
          CMP AL,'A'
          JL NEXT
          CMP AL,'Z'
          JB NEXT1
          ADD BH, 1
          INC SI
          LOOP AGAIN
          MOV AH, 4CH
          INT 21H

  NEXT:   CMP AL, '0'
          JL DONE
          CMP AL, '9'
          JB DONE
          ADD DH, 1
          INC SI
          LOOP AGAIN
          MOV AH, 4CH
          INT 21H

  DONE:   ADD DL, 1
          INC SI
          LOOP AGAIN 
          MOV AH, 4CH
          INT 21H

  NEXT1:  CMP AL, 'a'
          JL DONE
          CMP AL, 'z'
          JB DONE
          ADD BL, 1
          INC SI
          LOOP AGAIN
          MOV AH, 4CH
          INT 21H
          
CODE ENDS
    END START

第三版代码 

本来就觉得分支写的不符合题意,既然报错了,不妨改成子程序,现在好像也明白了为什么得用子程序写,子程序写的话,代码的逻辑简洁度会高一点

DATA SEGMENT
    S_OUT DB 'Please enter a string less than 10 characters:$'
    S_INT DB 10, ?, 10 DUP(10)
   
DATA ENDS

STACK SEGMENT STACK
    DB 100 DUP(?)
STACK ENDS

CODE SEGMENT 
    ASSUME DS:DATA, CS:CODE, SS:STACK
    START:
	      MOV AX, DATA
          MOV DS,AX

          MOV AH,09H
          LEA DX,S_OUT
          INT 21H

          MOV AH, 0AH
          LEA DX,S_INT
          INT 21H

          MOV [SI],DX
          MOV CX, 0
          MOV CX, SI+1
          MOV BX, 0
          MOV DX, 0
          CALL ENUMERATE
          
          MOV AH, 4CH
          INT 21H

ENUMERATE PROC
  AGAIN:  MOV AL,[SI]
          CMP AL,'A'
          JL NEXT
          CMP AL,'Z'
          JB NEXT1
          ADD BH, 1
          INC SI
          LOOP AGAIN
          RET

  NEXT:   CMP AL, '0'
          JL DONE
          CMP AL, '9'
          JB DONE
          ADD DH, 1
          INC SI
          LOOP AGAIN
          RET

  DONE:   ADD DL, 1
          INC SI
          LOOP AGAIN 
          RET
          

  NEXT1:  CMP AL, 'a'
          JL DONE
          CMP AL, 'z'
          JB DONE
          ADD BL, 1
          INC SI
          LOOP AGAIN
          RET

ENUMERATE ENDP
        
          
CODE ENDS
    END START

结果还是卡死,那问题很有可能出在了循环上

第四版代码 

后来发现是存储空间的问题,是声明原因还没搞清楚,猜想可能和定义空间存储有关,第一个单元存的是整个空间的长度,之后才存储字符

DATA SEGMENT
    S_OUT DB 'Please enter a string less than 10 characters:$'
    S_INT DB 10, ?, 10 DUP(10)   
DATA ENDS

STACK SEGMENT STACK
    DB 100 DUP(?)
STACK ENDS

CODE SEGMENT 
    ASSUME DS:DATA, CS:CODE, SS:STACK
    START:
	      MOV AX, DATA
          MOV DS,AX

          MOV AH,09H
          LEA DX,S_OUT
          INT 21H

          MOV AH, 0AH
          LEA DX,S_INT
          INT 21H

          MOV [SI],DX
          MOV CX, 0
          MOV CX, [SI+1]
          MOV BX, 0
          MOV DX, 0
          CALL ENUMERATE
          
          MOV AH, 4CH
          INT 21H

ENUMERATE PROC
  AGAIN:  MOV AL,[SI+1]
          CMP AL,'A'
          JL NEXT
          CMP AL,'Z'
          JB NEXT1
          ADD BH, 1
          INC SI
          LOOP AGAIN
          RET

  NEXT:   CMP AL, 30
          JL DONE
          CMP AL, 39
          JB DONE
          ADD DH, 1
          INC 
          LOOP AGAIN
          RET

  DONE:   ADD DL, 1
          INC SI
          LOOP AGAIN 
          RET
          

  NEXT1:  CMP AL, 'a'
          JL DONE
          CMP AL, 'z'
          JB DONE
          ADD BL, 1
          INC SI
          LOOP AGAIN
          RET

ENUMERATE ENDP
        
          
CODE ENDS
    END START

第五版代码 

逻辑有问题,连用了JL和JB两个判断符,导致寄存器存储的不是对应的值

符号JB/JA是一组(无符号数的判断),JL/JG是一组(有符号数的判段),下面的代码把判断大小搞混了

DATA SEGMENT
    S_OUT DB 'Please enter a string less than 10 characters:$'
    S_INT DB 11, ?, 11 DUP(11)   
DATA ENDS

STACK SEGMENT STACK
    DB 100 DUP(?)
STACK ENDS

CODE SEGMENT 
    ASSUME DS:DATA, CS:CODE, SS:STACK
    START:
	      MOV AX, DATA
          MOV DS,AX

          MOV AH,09H
          LEA DX,S_OUT
          INT 21H

          MOV AH, 0AH
          LEA DX,S_INT
          INT 21H

          MOV [SI],DX
          MOV CX, 0
          MOV CX, [SI+1]
          MOV BX, 0
          MOV DX, 0
          CALL ENUMERATE
          
          MOV AH, 4CH
          INT 21H

ENUMERATE PROC
  AGAIN:  MOV AL,[SI+1]
          CMP AL,'A'
          JL NEXT
          CMP AL,'Z'
          JB NEXT1
          ADD BH, 1
          INC SI
          LOOP AGAIN
          RET

  NEXT:   CMP AL, 30
          JL DONE
          CMP AL, 39
          JB DONE
          ADD DH, 1
          INC SI
          LOOP AGAIN
          RET

  DONE:   ADD DL, 1
          INC SI
          LOOP AGAIN 
          RET
          

  NEXT1:  CMP AL, 'a'
          JL DONE
          CMP AL, 'z'
          JB DONE
          ADD BL, 1
          INC SI
          LOOP AGAIN
          RET
ENUMERATE ENDP
        
          
CODE ENDS
    END START

今日小结 

写代码的快乐在于一次又一次的突破,剥开层层迷雾,最终走向那个正确的结果。
这哪是工作呀,这分明是学习,是享受啊,从知识的学习者转变为知识的应用者,成为知识的创造者,脑中的一个又一个可能,流淌到指尖,在键盘上不断跳跃,汇聚成一行行代码,开出灿烂而美妙的花朵,心中无比宁静,空气中充满了自由的味道

看到一个又一个关键点,寻找一种接一种的可能,带着期望,带着忐忑,带着兴奋不断尝试,最终,在那个恰当的时间,砰的一声,豁然开朗,长舒一口气,满是幸福

继续努力吧,做一个开心学习的人儿 

报告心路历程

亲爱的老师,这是我这次实验的心路历程,无人述说,可以的话,请允许我以这样的方式向您述说,和您接触很是亲切。

这是实验版块的最后一个报告,写完报告已是晚上八点,我从下午五点开始写,因为之前用将近三周的时间做完了实验的全部,只剩下最后的整理工作,所以时间不长。写完我就去吃饭了,此刻的食堂已是空无一人,很安静,微微亮起的几盏灯,指着出口。一人独坐,心中感到了巨大的落空感,这样的感受早已熟悉,每完成一次考试或实验就会有这样的感觉。但当它来临的一刻还是忍不住的波澜。我知道那是长久专注于一个目标的原因,当它完成的一刻,目标消失,一时不知何去何从。

我从来没有过用这样近乎疯狂的方式对待一门课程,课前的预习,课上笔不停,课后看PPT,说这些不是在表达我有多努力,这些是一个学生的本分,只是说这是我的又一次成长和突破,我体会到了成为一名合格学生的快乐,那是珠峰山顶的朝阳,一抹金黄,逐渐弥漫整个山谷,洒在我的身上,很是惬意,一抹清凉,还有些许自由。

我以此篇献给您,和您学习很是快乐,也是写给我自己,带着这美妙的经历继续向前。

此致,敬礼!

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值