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

汇编语言写入数组遇Segmentation fault错误,求问题原因及解决方法

问题分析与修复方案

你的汇编代码存在几个关键错误,直接导致了段错误,逐个拆解说明:

1. 直接用内存符号做比较操作

cmp %ecx, array_len这行是核心错误之一:array_len是.data段中分配的内存地址,而非存储在该地址里的长度数值。你需要先把array_len中的值加载到寄存器,再和循环计数器ecx比较:

movl array_len, %edx  # 将数组长度从内存读取到edx寄存器
cmp %ecx, %edx
je l_exit

2. scanf调用的参数逻辑错误

C标准库的scanf需要传入格式串和存储输入值的地址两个参数,你当前只压入了格式串,缺少存储地址。另外,你用pushl %eax保存寄存器的时机完全错误——scanf会直接覆盖eax(返回成功读取的元素个数),正确的调用方式应该是:

# 替换原循环内的scanf调用代码
leal (%edi, %ecx, 4), %ebx  # 计算当前数组元素的内存地址
pushl %ebx                   # 压入存储输入值的地址
pushl $inputFormat
call scanf
addl $8, %esp                # 手动平衡栈,替代两次无意义的popl

用addl $8, %esp清理栈比两次popl更简洁,也避免了错误覆盖寄存器。

3. 错误理解scanf的返回值

scanf不会把输入的数值存在eax里——eax返回的是成功读取的元素数量,输入的数值会直接写入你传入的地址中。你之前的movl %eax, (%edi, %ecx, 4)完全逻辑错误,要么直接让scanf把值写入数组元素地址(如上面的代码),要么先存在临时变量再转存。

修复后的循环完整代码

xorl %ecx, %ecx
lea array, %edi
movl array_len, %edx  # 提前加载数组长度到寄存器,避免每次循环都读内存

l_loop:
cmp %ecx, %edx
je l_exit

# 调用scanf写入当前数组元素
leal (%edi, %ecx, 4), %ebx
pushl %ebx
pushl $inputFormat
call scanf
addl $8, %esp

# 可选:检查scanf是否成功读取,避免输入错误导致死循环
cmpl $1, %eax
jne l_exit

incl %ecx
jmp l_loop

l_exit:
# 这里添加程序退出逻辑,比如ret

额外注意事项

  • 栈平衡:调用C函数后,要么用addl $n, %esp(n为参数总字节数),要么用pop清理栈,不要混用导致栈错位。
  • 寄存器保护:ebx、esi、edi属于非易失性寄存器,调用C函数前需要手动push到栈保存,调用后再pop恢复,避免被C函数破坏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 11:15:28