题目:在数据段中有从STRING单元开始存放的100个字节数据,编写程序要求将字符串中的大写字母转换为小写字母,并显示到屏幕上。
汇编源程序如下:
DATA SEGMENT ; 数据段定义
STRING DB 100
DB ?
BUF DB 100 DUP(?)
CNT EQU $-BUF
DATA ENDS
CODE SEGMENT ; 代码段定义
ASSUME CS:CODE,DS:DATA
START:
MOV AX,DATA
MOV DS,AX ;设置DS
LEA DX,STRING
MOV AH,10
INT 21H ;从键盘接收字符串
PUSH DX
PUSH AX
MOV DL,0DH
MOV AH,2
INT 21H
MOV DL,0AH
MOV AH,2
INT 21H
POP AX
POP DX ;回车换行
MOV CH,CNT ;总的字符个数
MOV SI,OFFSET BUF
NEXT:
MOV CL,[SI]
CMP CL,41H
JB NEXT2
CMP CL,5AH
JA NEXT2 ;判断是否是大写
ADD CL,20H ;把大写字母改为小写字母
NEXT2:
MOV DL,CL
MOV AH,2
INT 21H ;输出字符
MOV DL,20H
MOV AH,2
INT 21H ;输出空格
INC SI
DEC CH
JNZ NEXT
MOV AH,4CH
INT 21H
CODE ENDS
END START
查错经过:
仔细阅读一下代码,发现,这段代码里,有一处关于获取实际输入字符串个数的用法(第28行)有问题。
根据10号DOS功能调用的用法,从键盘实际输入的字符的个数应该保存在STRING+1单元,所以,这条指令应该改为MOV CH,STRING+1。
将修改后的程序汇编、连接后运行,结果正确,如下图所示。
尽管修改了一条指令后,程序可以正确运行了,但是,笔者的疑问依然存在。刚刚修改的一条指令,仅仅是关于循环次数的。为什么,循环次数比实际字符个数多的时候,无法正确显示结果呢?DEBUG.EXE是调试汇编程序的重要工具。为了解决这个问题,必须要借助DEBUG。
在命令窗口,执行DEBUG yxj.exe命令,调试该程序。下图所示,是调试窗口的情况。
进入DEBUG后,设置一个断点。这个断点应该设置在键盘输入DOS功能调用之后,结果输出之前。本次调试,笔者设置的断点是cs:000e处的指令。程序运行到断点处,停下来后,笔者利用D DS:0命令,查看了一下输入字符缓冲区。此次输入的字符串是Aa123,在输入缓冲区看到,在实际输入的字符串后面,10号调用执行后,自动在输入字符的后面插入字符串结束符0DH。现在谜底找到了。无法正常运行的程序,由于多输出了实际输入字符后面的全部输入缓冲区的内容,这其中包括0DH(这个符号是回车符)。这样,当输出到回车符时,光标回到显示行的最左边,将之前输出的内容全部覆盖了。因此,看到的现象是没有输出。
为了验证,笔者的判断是否正确。在DEBUG里,笔者临时修改了保存0DH值的单元的内容(用 E DS:7命令)。运行结果(见上图),正确。
心得:
汇编学习是一个需要耐心和恒心的过程。只有通过不断的上机练习,才能给真正掌握这门程序设计语言。本例提示我们,运行时发生的错误,应该从多个方面去查找问题,不应该孤立的查找错误。例如,本例出错的根本原因是字符串的个数弄错了,而运行后的表现却是没有显示。
这种错误的发生,是比较难查找的。