You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

错误分析

程序陷入无限循环及功能异常的核心原因如下:

  1. 输入文件描述符错误:使用ebx=2(标准错误流)读取输入,应改为ebx=0(标准输入流stdin)。
  2. 错误比较内存地址而非字符值:cmp ecx, 1Ch是比较num的内存地址与终止符1Ch(Ctrl+\的ASCII码),两者永远不可能相等,导致inputkey无限循环。需读取num存储的实际字符进行比较:cmp byte [num], 1Ch。
  3. 压入栈的是地址而非字符值:push ecx压入的是num的内存地址,而非用户输入的字符,导致后续输出逻辑完全错误。应压入实际读取的字符:push byte [num]。
  4. 输出系统调用参数错误: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

修正说明

  1. 输入部分:将文件描述符改为0,比较num中的字符值,压入实际字符到栈中,终止符不压入栈直接返回。
  2. 输出部分:通过检查栈指针判断是否输出完毕,弹出字符后存入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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 16:13:36