NASM仿Akinator游戏问题修复:首个答案复用至所有问题
NASM猜谜游戏答案复用问题修复
问题原因
- 输入缓冲区过小:原代码中
answer resb 2仅分配2字节空间,但用户输入"yes"/"no"加上回车符需要至少3字节,未读取的残留字符会留在输入流中,被后续sys_read直接读取,导致答案复用。 - 读取长度设置错误:每次调用
sys_read时edx设为2,仅读取2字节,无法完整读取用户输入(包括回车),残留数据会干扰后续输入。 - 字符串比较逻辑错误:
cmp byte [answer], 'yes'是单字节比较,仅判断第一个字符是否为'y',并非完整匹配"yes"。cmp word [answer], 'no'是双字节比较,但未考虑回车符,实际输入的"no"后会跟回车,导致比较逻辑失效,错误复用之前的输入判断。
修复后的代码
section .data ; questions q1 db 'Is your character real? (yes/no)', 0xA, 0 ; 添加换行符优化显示 q2 db 'Is your character human? (yes/no)', 0xA, 0 q3 db 'Is your character male? (yes/no)', 0xA, 0 q4 db 'Is your character fictional? (yes/no)', 0xA, 0 q5 db 'Is your object/animal living? (yes/no)', 0xA, 0 ; answers a1 db 'red', 0xA, 0 a2 db 'jabol', 0xA, 0 a3 db 'kuromi', 0xA, 0 a4 db 'pencil', 0xA, 0 ; 比较用的字符串 yes_str db 'yes' no_str db 'no' section .bss answer resb 10 ; 扩大缓冲区,足够容纳输入和回车 section .text global _start _start: ; 处理问题1 call print_q1 call read_answer call check_yes je human call check_no je object_animal jmp _start ; 输入无效时重新提问 human: ; 处理问题3(原代码中误写为q3,对应性别问题) call print_q3 call read_answer call check_yes je male call check_no je female jmp human ; 输入无效时重新提问 male: call print_a1 jmp exit female: call print_a2 jmp exit object_animal: ; 处理问题5 call print_q5 call read_answer call check_yes je living call check_no je non_living jmp object_animal ; 输入无效时重新提问 living: call print_a3 jmp exit non_living: call print_a4 jmp exit ; 打印问题1 print_q1: mov eax, 4 mov ebx, 1 mov ecx, q1 mov edx, 26 ; 包含换行符的长度 int 0x80 ret ; 打印问题3 print_q3: mov eax, 4 mov ebx, 1 mov ecx, q3 mov edx, 32 ; 包含换行符的长度 int 0x80 ret ; 打印问题5 print_q5: mov eax, 4 mov ebx, 1 mov ecx, q5 mov edx, 32 ; 包含换行符的长度 int 0x80 ret ; 打印答案a1 print_a1: mov eax, 4 mov ebx, 1 mov ecx, a1 mov edx, 5 ; 包含换行符的长度 int 0x80 ret ; 打印答案a2 print_a2: mov eax, 4 mov ebx, 1 mov ecx, a2 mov edx, 6 ; 包含换行符的长度 int 0x80 ret ; 打印答案a3 print_a3: mov eax, 4 mov ebx, 1 mov ecx, a3 mov edx, 7 ; 包含换行符的长度 int 0x80 ret ; 打印答案a4 print_a4: mov eax, 4 mov ebx, 1 mov ecx, a4 mov edx, 8 ; 包含换行符的长度 int 0x80 ret ; 读取用户输入 read_answer: mov eax, 3 mov ebx, 0 mov ecx, answer mov edx, 10 ; 读取足够长度,覆盖缓冲区 int 0x80 ; 清理缓冲区中回车后的内容,确保下次输入不受干扰 mov esi, answer clean_buffer: cmp byte [esi], 0xA ; 找到回车符 je clean_done inc esi cmp esi, answer+10 jb clean_buffer clean_done: mov byte [esi], 0 ; 用0截断字符串 ret ; 检查输入是否为yes check_yes: mov esi, answer mov edi, yes_str cmpsb jne check_yes_fail cmpsb jne check_yes_fail cmpsb jne check_yes_fail mov eax, 1 ret check_yes_fail: mov eax, 0 ret ; 检查输入是否为no check_no: mov esi, answer mov edi, no_str cmpsb jne check_no_fail cmpsb jne check_no_fail mov eax, 1 ret check_no_fail: mov eax, 0 ret exit: mov eax, 1 xor ebx, ebx int 0x80
修复说明
- 扩大缓冲区:将
answer的大小改为10字节,足够容纳用户输入及回车符,避免残留数据。 - 完整读取输入:
sys_read的edx设为10,每次读取足够长度,并用截断操作清理回车后的内容,确保缓冲区干净。 - 添加字符串比较函数:通过
check_yes和check_no函数实现完整的字符串匹配,避免单/双字节比较的逻辑错误。 - 优化显示:给问题和答案添加换行符,提升交互体验。
- 输入校验:添加无效输入时重新提问的逻辑,增强程序健壮性。
内容的提问来源于stack exchange,提问作者Duncan Red Benedict De Guzman
相关产品推荐
相关产品推荐

