TASM汇编大写转小写代码故障:键盘输入无法正常执行
修复TASM大写转小写程序的键盘输入问题
我来帮你梳理代码里的核心问题,一步步修复让它能正常处理键盘输入,完成大写转小写、输出结果并统计字符数的功能:
原代码的主要问题
- 循环控制完全失控:你用了
LOOPNE L1,但LOOP系列指令依赖CX寄存器做循环计数器,可代码里根本没初始化CX的值,这会导致循环行为完全不可预测。另外,你只判断$作为结束符,但没处理用户按回车的情况,输入回车后程序会一直卡着。 - 字符计数逻辑错误:当前只有输入空格时才会
INC BL,这和你要统计“读取的总字符数”的需求完全不符,应该每读取一个有效字符(非结束符)就计数一次。 - 字符串结束符缺失:
INT 21H的09H功能需要字符串以$结尾才能正常输出,原代码没在缓冲区末尾添加这个结束符,会导致输出乱码。 - 计数输出有bug:
ADD BL, 01会多统计一个字符,而且如果字符数超过9,原代码只能输出单个数字,没法显示两位的数值。
修正后的完整代码
DATA SEGMENT PARA PUBLIC 'DATA' SIR DB 101 DUP (?) ; 多留1个位置存字符串结束符$ newline DB 10,13,'$' count_prompt DB 10,13,'Total characters read: $' DATA ENDS CODE SEGMENT PARA PUBLIC 'CODE' ASSUME CS:CODE, DS:DATA, ES:DATA ; 大写转小写的子过程 to_lower PROC FAR ; 如果不是大写字母,直接返回 CMP AL, 'A' JB exit_proc CMP AL, 'Z' JA exit_proc ; 大写转小写,ASCII码差值为20H ADD AL, 20H exit_proc: RET to_lower ENDP START PROC FAR PUSH DS XOR AX, AX PUSH AX MOV AX, DATA MOV DS, AX MOV ES, AX MOV CX, 100 ; 初始化最大字符数(最多读100个) MOV BL, 0 ; 初始化字符计数器 MOV DI, OFFSET SIR CLD ; 方向标志置0,STOSB会自动递增DI read_loop: MOV AH, 01H ; 读取键盘输入并回显 INT 21H ; 判断是否触发结束输入:回车(0DH)或$ CMP AL, 0DH JE end_read CMP AL, '$' JE end_read ; 检查是否已经读满100个字符 JCXZ end_read ; 调用大写转小写子过程 CALL to_lower ; 将转换后的字符存入缓冲区 STOSB INC BL ; 字符计数+1 LOOP read_loop ; CX减1,不为0则继续循环 end_read: ; 在缓冲区末尾添加$,确保09H功能能正确输出 MOV BYTE PTR [DI], '$' ; 输出换行 LEA DX, newline MOV AH, 09H INT 21H ; 输出转换后的文本 MOV DX, OFFSET SIR MOV AH, 09H INT 21H ; 输出字符数提示 LEA DX, count_prompt MOV AH, 09H INT 21H ; 处理两位数字的输出(最多100个字符,范围0-99) MOV AL, BL MOV AH, 0 MOV DL, 10 DIV DL ; AL=十位数字,AH=个位数字 MOV CL, AH ; 暂存个位 ; 输出十位 MOV DL, AL ADD DL, 30H ; 转ASCII码 MOV AH, 02H INT 21H ; 输出个位 MOV DL, CL ADD DL, 30H MOV AH, 02H INT 21H ; 退出程序 MOV AH, 4CH INT 21H START ENDP CODE ENDS END START
关键修改说明
- 循环控制修复:初始化
CX为100,用LOOP read_loop控制最多读取100个字符,同时支持回车和$两种结束输入的方式,符合日常键盘输入习惯。 - 计数逻辑修正:每读取一个有效字符(非结束符)就执行
INC BL,准确统计读取的总字符数。 - 字符串结束符处理:输入结束后手动给缓冲区添加
$,确保INT 21H 09H能正确输出转换后的文本,不会出现乱码。 - 字符数输出优化:支持两位数字的显示,解决原代码只能显示个位数的问题,适配最多100个字符的统计需求。
内容的提问来源于stack exchange,提问作者Lola




