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

方阵乘法汇编程序出现Segmentation fault错误,求助定位修复

方阵乘法汇编程序段错误分析与修复

错误原因分析

  1. 栈帧基址寄存器ebp被非法修改
    程序初始化时通过movl %esp, %ebp建立栈帧,后续在matrix_loop中执行movl $0, %ebp将ebp清零。原本20(%ebp)用于获取参数N,此时ebp为0,[ebp+0x14]指向0x14这个非法内存地址,直接触发段错误。

  2. 矩阵乘法逻辑完全错误
    当前内循环仅遍历A和B的同一偏移元素相乘,不符合矩阵乘法的规则——矩阵C的元素C[i][j]应该是A的第i行与B的第j列对应元素相乘后的累加和。

  3. 循环计数器冲突
    外层循环使用eax作为计数器,但eax在内循环中被用来存储A的元素值,执行incl %eax会破坏外层循环的计数逻辑。

修复方案

修正后的汇编代码

matrix_mult:
pushl %ebp        # 保存ebp到栈,建立栈帧前的准备
movl %esp, %ebp   # 初始化栈帧基址
pushl %ebx        # 遵循cdecl调用约定,保存被调用者保存寄存器
pushl %esi
pushl %edi
    
movl 8(%ebp), %ebx  # 获取矩阵A的基地址
movl 12(%ebp), %ecx # 获取矩阵B的基地址
movl 16(%ebp), %edx # 获取矩阵C的基地址
movl 20(%ebp), %edi # 获取方阵大小N

xorl %eax, %eax   # 外层循环计数器i(行号)初始化为0
matrix_loop:
    cmpl %edi, %eax
    jge end_matrix_loop  # i >= N时退出外层循环

    xorl %esi, %esi       # 内层循环计数器j(列号)初始化为0
inner_loop:
    cmpl %edi, %esi
    jge end_inner_loop    # j >= N时退出内层循环

    # 准备计算C[i][j]:保存i、j到栈,初始化累加和sum=0
    pushl %eax
    pushl %esi
    pushl $0

    xorl %ecx, %ecx       # sum循环计数器k初始化为0
sum_loop:
    cmpl %edi, %ecx
    jge end_sum_loop

    # 读取A[i][k]:地址 = A + (i*N + k)*4
    movl 8(%esp), %edx    # 取出i
    leal (%edx,%edi,1), %edx # 计算i*N
    addl %ecx, %edx         # i*N + k
    movl (%ebx,%edx,4), %edx # 读取A[i][k]

    # 读取B[k][j]:地址 = B + (k*N + j)*4
    movl 4(%esp), %eax    # 取出j
    leal (%ecx,%edi,1), %eax # 计算k*N
    addl 4(%esp), %eax     # k*N + j
    movl (%ecx,%eax,4), %eax # 读取B[k][j]

    mull %edx               # 计算A[i][k] * B[k][j],结果低32位在eax
    addl %eax, (%esp)       # 累加到sum

    incl %ecx
    jmp sum_loop
end_sum_loop:
    # 将sum写入C[i][j]:地址 = C + (i*N + j)*4
    movl (%esp), %eax      # 取出sum
    movl 8(%esp), %ecx     # 取出i
    leal (%ecx,%edi,1), %ecx # i*N
    addl 4(%esp), %ecx     # i*N + j
    movl %eax, (%edx,%ecx,4) # 写入C[i][j]

    # 恢复寄存器,继续循环
    addl $4, %esp          # 弹出sum
    popl %esi
    popl %eax

    incl %esi               # j++
    jmp inner_loop
end_inner_loop:
    incl %eax               # i++
    jmp matrix_loop
end_matrix_loop:
# 恢复被调用者保存寄存器,销毁栈帧
popl %edi
popl %esi
popl %ebx
popl %ebp
ret

关键修改说明

  1. 保护栈帧基址ebp
    全程不再修改ebp,所有参数访问(如12(%ebp)获取B的指针)都基于原始栈帧,彻底避免非法内存访问导致的段错误。

  2. 实现正确的矩阵乘法逻辑
    新增sum_loop循环,遍历k从0到N-1,计算A的第i行与B的第j列对应元素的乘积并累加,符合矩阵乘法的数学定义。

  3. 规范寄存器管理

    • 遵循cdecl调用约定,保存并恢复ebx、esi、edi这些被调用者保存寄存器,避免破坏调用者的寄存器状态。
    • 为不同循环分配独立的计数器寄存器:外层用eax(i)、内层用esi(j)、sum循环用ecx(k),避免寄存器冲突覆盖。
  4. 修正内存寻址
    正确计算矩阵元素的内存地址:对于N阶方阵,元素M[x][y]的地址为基地址 + (x*N + y)*4(假设每个元素是4字节的32位整数)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 00:30:44