x86汇编:如何实现控制台无回显的用户密码输入
嘿,我完全懂你现在的困扰——用Irvine32的ReadInt确实会直接回显输入内容,这对于密码/ID这类需要隐藏的输入场景太不友好了。别担心,咱们可以通过控制控制台的回显模式,配合逐字符读取的方式来解决这个问题,下面给你一步步讲清楚:
核心思路
Windows控制台本身有模式控制位,其中ENABLE_ECHO_INPUT负责控制输入是否回显。我们可以先保存当前的控制台模式,关闭回显位,然后用ReadChar逐个读取用户输入(不自动回显),最后再恢复原来的控制台模式,避免影响后续操作。同时还要处理退格键这类特殊输入,让用户体验更自然。
完整实现代码
INCLUDE Irvine32.inc .data idPromptStr byte "Please enter ID : ", 13, 10, 0 inputBuffer byte 10 dup(0) ; 存储输入的数字字符,最多支持9位ID(加结束符) id DWORD ? originalMode DWORD ? ; 保存原始控制台模式,用于后续恢复 .code main proc ; 1. 获取并保存当前控制台输入模式 invoke GetConsoleMode, GetStdHandle(STD_INPUT_HANDLE), addr originalMode ; 关闭回显位:用AND NOT清除ENABLE_ECHO_INPUT(宏定义为4) mov eax, originalMode and eax, NOT ENABLE_ECHO_INPUT invoke SetConsoleMode, GetStdHandle(STD_INPUT_HANDLE), eax ; 显示输入提示 mov edx, OFFSET idPromptStr call WriteString ; 2. 逐字符读取输入,无回显处理 mov esi, OFFSET inputBuffer mov ecx, 0 ; 记录已输入的字符数量 readLoop: call ReadChar ; 读取单个字符到AL寄存器 cmp al, 13 ; 判断是否按下回车键(ASCII码13) je endRead ; 是回车则结束输入 cmp al, 8 ; 判断是否按下退格键(ASCII码8) je handleBackspace ; 只接受数字字符 cmp al, '0' jb readLoop ; 小于'0'则跳过 cmp al, '9' ja readLoop ; 大于'9'则跳过 ; 合法数字存入缓冲区 mov [esi], al inc esi inc ecx jmp readLoop handleBackspace: cmp ecx, 0 ; 没有输入过字符则忽略退格 je readLoop ; 回退缓冲区指针并清空对应位置 dec esi dec ecx mov byte ptr [esi], 0 ; 在控制台模拟退格视觉效果:退格+空格+退格 mov al, 8 call WriteChar mov al, ' ' call WriteChar mov al, 8 call WriteChar jmp readLoop endRead: ; 3. 将输入的数字字符串转换为整数(替代ReadInt的功能) mov edx, OFFSET inputBuffer call ParseDecimal32 ; Irvine32内置函数,把字符串转成EAX中的整数 mov id, eax ; 4. 恢复原始控制台模式,避免影响后续操作 invoke SetConsoleMode, GetStdHandle(STD_INPUT_HANDLE), originalMode ; 可选:测试输出验证ID是否正确读取 call Crlf mov edx, OFFSET inputBuffer call WriteString call Crlf mov eax, id call WriteDec call Crlf exit main endp end main
关键细节说明
- 控制台模式修改:
GetConsoleMode和SetConsoleMode是Windows API,Irvine32允许直接用invoke调用,GetStdHandle(STD_INPUT_HANDLE)用于获取标准输入的句柄。 - 退格处理:不仅要修改输入缓冲区,还要在控制台输出退格+空格+退格,这样用户能直观看到输入的字符被删除,体验更流畅。
- 字符串转整数:用Irvine32的
ParseDecimal32函数替代ReadInt,它能把我们收集到的数字字符串转换成32位整数,完美匹配你原来的需求。 - 缓冲区大小:示例中设置的
inputBuffer是10字节,如果你需要支持更长的ID,直接调整这个值即可(注意预留一个字节给字符串结束符)。
内容的提问来源于stack exchange,提问作者E spir
相关产品推荐
相关产品推荐

