使用NASM实现字符逆序显示(程序陷入无限循环)
NASM汇编程序无限循环问题排查与修复
问题背景
编写的NASM汇编程序预期实现接收字符并逆序显示功能,但运行时陷入无限循环。原代码及编译步骤如下:
原程序代码
section .bss num resb 1 section .text global _start _start: call inputkey call outputkey ;程序退出 mov eax, 1 mov ebx, 0 int 80h inputkey: ;读取用户输入 mov eax, 3 mov ebx, 2 mov ecx, num mov edx, 1 int 80h cmp ecx, 1Ch je .sub2 push ecx jmp inputkey .sub2: push ecx ret outputkey: pop ecx ;输出字符 mov eax, 4 mov ebx, 1 ;mov ecx, num mov edx, 1 int 80h cmp ecx, 1Ch je .sub1 jmp outputkey .sub1: ret
原编译运行步骤
文件名:logic.asm
执行命令:
nasm -f elf logic.asm ld -m elf_i386 -s -o logic logic.o ./logic
错误分析
程序陷入无限循环及功能异常的核心原因如下:
- 输入文件描述符错误:使用
ebx=2(标准错误流)读取输入,应改为ebx=0(标准输入流stdin)。 - 错误比较内存地址而非字符值:
cmp ecx, 1Ch是比较num的内存地址与终止符1Ch(Ctrl+\的ASCII码),两者永远不可能相等,导致inputkey无限循环。需读取num存储的实际字符进行比较:cmp byte [num], 1Ch。 - 压入栈的是地址而非字符值:
push ecx压入的是num的内存地址,而非用户输入的字符,导致后续输出逻辑完全错误。应压入实际读取的字符:push byte [num]。 - 输出系统调用参数错误:
write系统调用(eax=4)要求ecx指向输出缓冲区,原代码直接使用ecx存储的字符值会导致非法内存访问,且循环判断同样错误比较地址与终止符。
修正后的代码
section .bss num resb 1 section .text global _start _start: call inputkey call outputkey ;程序退出 mov eax, 1 mov ebx, 0 int 80h inputkey: ;从标准输入读取1个字符,存入num mov eax, 3 mov ebx, 0 ; 修正:使用标准输入(stdin) mov ecx, num mov edx, 1 int 80h cmp byte [num], 1Ch ; 修正:比较num中的字符值与终止符1Ch je .sub2 push byte [num] ; 修正:压入实际输入的字符值 jmp inputkey .sub2: ; 终止符不需要压入栈,直接返回 ret outputkey: ; 检查栈是否为空(防止无输入时出错) cmp esp, ebp je .sub1 pop ecx ; 弹出栈中存储的字符值 ; 将字符存入num作为输出缓冲区 mov [num], cl ; 输出num中的字符 mov eax, 4 mov ebx, 1 mov ecx, num ; 修正:指向输出缓冲区地址 mov edx, 1 int 80h jmp outputkey ; 继续弹出输出,直到栈空 .sub1: ret
修正说明
- 输入部分:将文件描述符改为
0,比较num中的字符值,压入实际字符到栈中,终止符不压入栈直接返回。 - 输出部分:通过检查栈指针判断是否输出完毕,弹出字符后存入
num缓冲区,调用write输出,直到栈空后返回,避免无限循环。
编译运行验证
使用原编译命令重新编译运行:
nasm -f elf logic.asm ld -m elf_i386 -s -o logic logic.o ./logic
运行时输入任意字符,按下Ctrl+\(对应ASCII码1Ch)结束输入,程序会逆序显示之前输入的所有字符。
内容的提问来源于stack exchange,提问作者Sri Tamal Chakraborty
相关产品推荐
相关产品推荐

