TASM x86汇编用户输入合法性校验问题求助
TASM x86输入校验问题修复
问题分析与修复点
1. 输入数字仍返回无效的原因
DOS中断int 21h的0Ah号功能(读取字符串)要求缓冲区遵循固定结构:
- 第1字节:缓冲区最大容纳字符数
- 第2字节:实际输入的字符数(由系统填充)
- 第3字节及以后:存储输入的字符(不含回车符)
你的代码中input_buffer仅定义了单个字节db 100,完全不符合0Ah的要求,导致输入数据存储混乱,校验逻辑读取到错误的起始位置,自然判定输入无效。
修复:
修改缓冲区定义为:
input_buffer db 100, 0, 100 dup(0)
同时,调用校验函数时,需要指向输入内容的起始位置(缓冲区+2),而非缓冲区开头:
; 原代码 mov si, offset input_buffer ; 修改为 mov si, offset input_buffer + 2
2. 第二次输入控制台冻结的原因
- 第一次输入后未处理回车符,控制台光标停留在输入行末尾,第二次输入时输出提示和读取操作的交互异常;
- 校验函数
CheckNumberExit中的jmp valid_input跳过了ret指令,导致函数未正确返回,破坏了程序栈结构,后续执行逻辑混乱; - 输入缓冲区未重置,残留的旧数据可能干扰第二次输入校验。
修复:
- 移除
CheckNumberExit中的jmp valid_input,仅保留ret让函数正常返回:
CheckNumberExit: mov al, 1 ; 输入有效时置al=1 ret ; 移除jmp valid_input
- 在读取输入后添加换行处理,让光标回到新行:
; 读取输入后添加以下代码 mov ah, 02h mov dl, 0Dh int 21h mov dl, 0Ah int 21h
- 在
InvalidInput输出错误信息后,同样添加换行,并重置缓冲区的实际输入长度为0:
InvalidInput: mov ah, 09h mov dx, offset invalid_msg int 21h ; 添加换行 mov ah, 02h mov dl, 0Dh int 21h mov dl, 0Ah int 21h ; 重置缓冲区实际长度 mov byte ptr [input_buffer+1], 0 xor al, al ; 置al=0表示无效 ret
完整修复代码
.model small .stack 200h .data prompt_msg1 db "Enter the first number: $" prompt_msg2 db "Enter the second number: $" valid_input_msg db "valid input$" invalid_msg db "Invalid input, please enter a valid number $" ; 修复缓冲区结构:最大长度、实际长度、存储区 input_buffer db 100, 0, 100 dup(0) .code start: mov ax, @data mov ds, ax GetFirstNumber: ; 提示输入第一个数字 mov ah, 09h mov dx, offset prompt_msg1 int 21h ; 读取用户输入到缓冲区 mov ah, 0Ah mov dx, offset input_buffer int 21h ; 处理回车换行,光标移至新行 mov ah, 02h mov dl, 0Dh int 21h mov dl, 0Ah int 21h ; 校验输入有效性,指向输入内容起始位置 mov si, offset input_buffer + 2 call CheckNumber cmp al, 0 je GetFirstNumber GetSecondNumber: ; 提示输入第二个数字 mov ah, 09h mov dx, offset prompt_msg2 int 21h ; 读取用户输入到缓冲区 mov ah, 02h mov dl, 0Dh int 21h mov dl, 0Ah int 21h mov ah, 0Ah mov dx, offset input_buffer int 21h ; 处理回车换行 mov ah, 02h mov dl, 0Dh int 21h mov dl, 0Ah int 21h ; 校验输入有效性 mov si, offset input_buffer + 2 call CheckNumber cmp al, 0 je GetSecondNumber valid_input: ; 输出有效提示 mov ah, 09h mov dx, offset valid_input_msg int 21h jmp Exit CheckNumber: xor al, al mov bl, [si] ; 处理空输入 cmp bl, 0Dh je InvalidInput cmp bl, '-' je CheckNumberSign cmp bl, '0' jl InvalidInput cmp bl, '9' jg InvalidInput inc si jmp CheckNumberDecimal CheckNumberSign: inc si mov bl, [si] cmp bl, '0' jl InvalidInput cmp bl, '9' jg InvalidInput inc si jmp CheckNumberDecimal CheckNumberDecimal: mov bl, [si] ; 输入结束符是回车(0Dh),不是0 cmp bl, 0Dh je CheckNumberExit cmp bl, '.' je CheckNumberDecimalPoint cmp bl, '0' jl InvalidInput cmp bl, '9' jg InvalidInput inc si jmp CheckNumberDecimal CheckNumberDecimalPoint: inc si mov bl, [si] cmp bl, '0' jl InvalidInput cmp bl, '9' jg InvalidInput inc si jmp CheckNumberDecimal CheckNumberExit: mov al, 1 ; 输入有效时置al=1 ret InvalidInput: mov ah, 09h mov dx, offset invalid_msg int 21h ; 换行处理 mov ah, 02h mov dl, 0Dh int 21h mov dl, 0Ah int 21h ; 重置缓冲区实际长度 mov byte ptr [input_buffer+1], 0 xor al, al ; 置al=0表示无效 ret Exit: mov ax, 4c00h int 21h end start
额外说明:原代码中valid_input_msg和invalid_msg末尾的0是多余的,DOS 09h功能以$作为结束符,所以去掉了多余的0;校验逻辑中把结束符从0改为0Dh(回车),因为0Ah读取的输入内容末尾是回车,而非0。
内容的提问来源于stack exchange,提问作者marcelo
相关产品推荐
相关产品推荐

