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

i386汇编实现C可调用的字符串字符计数功能出现死循环如何修复?

问题排查与修复方案

你的代码死循环的核心原因是没有正确递增字符串指针,同时还存在几处汇编语法和调用约定的错误,具体问题和修复点如下:

存在的问题

    1. 指针未递增导致死循环:你当前的incb %bl修改的是从字符串中读取到的当前字符值,而非指向字符串的指针%esi,导致每次循环永远读取字符串的第一个字符,永远无法走到结束符\0
    1. AT&T汇编立即数语法错误:cmp 0, %bl中的立即数0缺少$前缀,会被识别为内存地址0而非数字0,同时指令未指定操作长度后缀,可能产生预期外的行为
    1. 未遵循cdecl调用约定保存寄存器:%esi属于32位C调用约定中被调用者需保留的寄存器,你直接修改未做栈保存,会导致调用该函数的上层C程序运行异常
    1. 冗余栈空间分配:subl $12, %esp分配的12字节栈空间没有被使用,属于冗余代码

修复后的完整代码

.text
.global count

count:
    pushl   %ebp        # 构建栈帧
    movl    %esp, %ebp
    pushl   %esi        # 保存被调用者需保留的esi寄存器
    movl    $0, %eax    # 初始化计数器(返回值存在eax中)
    movl    8(%ebp), %esi   # 取第一个参数:字符串指针string
    movb    12(%ebp), %ch   # 取第二个参数:待匹配字符c,存到ch避免和后面的bl冲突

check:
    movb    (%esi), %bl # 读取当前指针指向的字符
    cmpb    $0, %bl     # 判断是否是字符串结束符\0
    je      done        # 到结尾则退出

    cmpb    %ch, %bl    # 对比当前字符和目标字符
    je      found       # 匹配则计数器+1
back:
    incl    %esi        # 指针递增,指向下一个字符(核心修复点)
    jmp     check

found:
    addl    $1, %eax    # 计数器+1
    jmp     back        # 回到公共的指针递增逻辑
    
done:
    popl    %esi        # 恢复esi寄存器
    movl    %ebp, %esp  # 销毁栈帧
    popl    %ebp
    ret

.end

修复说明

  1. 删掉了冗余的栈空间分配代码
  2. 增加了%esi的入栈保存和出栈恢复逻辑,符合cdecl调用约定
  3. 把incb %bl替换为incl %esi,每次循环正确移动字符串指针
  4. 给所有字节操作的cmp指令加上了b后缀,立即数加上了$前缀,符合AT&T汇编语法
  5. 拆分出公共的指针递增逻辑,避免重复写相同代码

内容的提问来源于stack exchange,提问作者leaTheBest

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 08:06:03