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

x86汇编实现str2int函数触发Segmentation Fault问题求助

问题定位与修复

段错误根本原因

你遇到的段错误主要是汇编代码编译架构不匹配导致的:在64位系统下,as汇编器默认生成64位目标文件,而你用gcc -m32链接32位C代码时,会出现指令集不兼容,导致程序执行时栈帧混乱、寄存器值异常,最终触发非法内存访问。

其次,代码本身存在两处逻辑问题,虽不直接导致段错误,但会影响功能正确性:

  1. 未遵循x86 cdecl调用约定,未保存/恢复非易失性寄存器edi、ebx
  2. 循环条件错误,遗漏处理字符串索引0的字符
  3. 全局变量number未重置,多次调用会导致结果累加

修复步骤

1. 正确编译32位汇编代码

编译汇编文件时必须指定--32参数,生成32位目标文件:

as --32 -o string2integer.o string2integer.s
as --32 -o count_chars.o count_chars.s
gcc -m32 -o test test.c string2integer.o count_chars.o

2. 修正str2int函数代码

以下是修复后的汇编代码,包含寄存器保护、循环逻辑修正和全局变量重置:

#string2integer.s
.data
number: .long 0

.globl str2int
.type str2int, @function

str2int:
    pushl %ebp
    movl %esp, %ebp
    # 保存非易失性寄存器(cdecl约定要求)
    pushl %edi
    pushl %ebx

    # 重置全局变量number为0
    movl $0, number

    # 获取字符串地址
    movl 8(%ebp), %edi

    # 调用count_chars获取字符串长度
    pushl 8(%ebp)
    call count_chars
    addl $4, %esp

    # 初始化计数器为最后一个字符索引
    movl %eax, %ecx
    decl %ecx

    # 初始化乘数为1
    movl $1, %ebx

str2int_lp:
    # 当计数器小于0时退出循环(处理所有索引从len-1到0)
    cmpl $-1, %ecx
    je str2int_end

    # 读取当前字符并转换为数字
    movzbl (%edi,%ecx,1), %eax
    subl $'0', %eax

    # 计算当前位的数值并累加
    imull %ebx, %eax
    addl %eax, number
    
    # 更新计数器和乘数
    decl %ecx
    imull $10, %ebx
    jmp str2int_lp

str2int_end:
    # 准备返回值
    movl number, %eax
    # 恢复非易失性寄存器
    popl %ebx
    popl %edi
    # 销毁栈帧
    movl %ebp, %esp
    popl %ebp
    ret

3. 验证修复

编译运行后,输入字符串"331"会正确输出331,且多次调用不会出现累加错误,也不会触发段错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 08:55:53