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

x86 32位Linux汇编矩阵乘法程序出现无限循环,求排查

32位Linux下x86汇编矩阵乘法无限循环问题修复

在32位Linux环境中用x86汇编实现矩阵乘法时,三层for循环陷入无限循环,核心问题出在栈帧局部变量分配错误和循环条件逻辑颠倒,以下是具体分析与修复方案:

原代码

.data段

m1: .long 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0
m2: .long 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0
mres: .long 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
n: .long 4
fs: .asciz "%ld"

.text段(matrix_mult函数)

matrix_mult:

    pushl %ebp
    mov %esp, %ebp
    
    pushl %edi
    pushl %esi
    pushl %ebx
    
    subl $12, %ebp
    // -16(ebp) = i
    // -20(ebp) = j
    // -24(ebp) = k
    
    subl $8, %ebp
    // -28(ebp) = x
    // -32(ebp) = y locul unde stocam elem din cele 2 matrici
    movl $0, -16(%ebp)
    movl $0, -20(%ebp)
    movl $0, -24(%ebp)
    
    et_for1:
        
        mov -16(%ebp), %eax
        mov 20(%ebp), %ecx
        cmp %eax, %ecx
        jge final
        movl $0, -20(%ebp)
            et_for2:
                
                mov -20(%ebp), %eax
                mov 20(%ebp), %ecx
                cmp %eax, %ecx
                jge cont_for2
                movl $0, -24(%ebp)
                    et_for3:
                        mov -24(%ebp), %eax
                        mov 20(%ebp), %ecx
                        cmp %eax, %ecx
                        jge cont_for3
                        
                        //mres[i][j]=m1[i][k]*m2[k][j]
                        lea 8(%ebp), %edi
                        lea 12(%ebp), %esi
                        //ecx=i*n+k, ecx= indicele pt m1
                        mov -16(%ebp), %eax
                        xorl %edx, %edx
                        mull 20(%ebp)
                        addl -24(%ebp), %eax
                        mov %eax, %ecx
                        //eax=k*n+j, eax= indicele pt m2
                        mov -24(%ebp) , %eax
                        xorl %edx, %edx
                        mull 20(%ebp)
                        addl -20(%ebp), %eax
                        
                        //ecx = produsul termenilor
                        mov (%edi, %ecx, 4), %ebx
                        mov %ebx, -28(%ebp)
                        mov (%esi, %eax, 4), %ebx
                        mov %ebx, -32(%ebp)
                        mov -28(%ebp), %eax
                        xorl %edx, %edx
                        mull -32(%ebp)
                        mov %eax, %ecx
                        
                        //eax=i*n+j
                        movl -16(%ebp), %eax
                        xorl %edx, %edx
                        mull 20(%ebp)
                        movl -20(%ebp), %ebx
                        addl %ebx, %eax
                        //ecx= prod term + mres[i][j]
                        lea 16(%ebp), %edi
                        movl (%edi, %eax, 4), %ebx
                        movl %ebx, -28(%ebp)
                        addl -28(%ebp), %ecx
                        
                        movl %ecx, (%edi, %eax, 4)
                    
                    mov -24(%ebp), %ebx
                    incl %ebx
                    mov %ebx, -24(%ebp) 
                    //k++
                    jmp et_for3
            cont_for3:
                
            mov -20(%ebp), %ebx
            incl %ebx
            mov %ebx, -20(%ebp) 
            mov $0, -24(%ebp)
            //j++ si k=0
            jmp et_for2 
                    
    
    cont_for2:
    
        
    mov -16(%ebp), %ebx
    incl %ebx
    mov %ebx, -16(%ebp) 
    //i++
    jmp et_for1
    
    final:
        addl $20, %esp
        popl %ebx
        popl %esi
        popl %edi
        popl %ebp
        ret

main函数

.global main
main:
pushl n
pushl mres
pushl m2
pushl m1
call matrix_mult
addl $16, %esp

lea mres, %edi
mov $0, %ecx
mov n, %eax
xorl %edx, %edx
mull %eax 
//eax=n*n

et_for:
    
    cmp %eax, %ecx
    je et_exit
    
    mov (%edi, %ecx, 4), %ebx
    pushl %eax
    pushl %ecx

    
    //afisare ebx
    push %ebx
    push $fs
    call printf
    addl $8, %esp
    
    push $0
    call fflush
    addl $4, %esp
    
    
    popl %ecx
    popl %eax
    incl %ecx
    
jmp et_for
    
et_exit:

mov $1, %eax
xorl %ebx, %ebx
int $0x80

问题分析

  1. 栈帧局部变量分配错误:
    分配局部变量时错误修改了%ebp寄存器(subl $12, %ebp、subl $8, %ebp),%ebp作为栈帧基址应保持固定,局部变量空间需通过修改%esp来分配。错误修改%ebp会导致所有基于%ebp的参数、局部变量偏移计算完全错误,循环条件中读取的n值变成栈内垃圾数据,引发无限循环。

  2. 循环条件逻辑颠倒:
    三层循环的退出条件判断逻辑错误,原代码用cmp %eax, %ecx(比较n和循环变量)配合jge跳转,导致循环未执行或退出条件永远不满足。正确逻辑应为当循环变量>=n时退出,需将cmp操作数顺序颠倒。

修复后的代码

.text段(matrix_mult函数)

matrix_mult:

    pushl %ebp
    mov %esp, %ebp
    
    pushl %edi
    pushl %esi
    pushl %ebx
    
    // 修复:用%esp分配局部变量空间,而非修改%ebp
    subl $12, %esp
    // -16(ebp) = i
    // -20(ebp) = j
    // -24(ebp) = k
    
    subl $8, %esp
    // -28(ebp) = x
    // -32(ebp) = y locul unde stocam elem din cele 2 matrici
    movl $0, -16(%ebp)
    movl $0, -20(%ebp)
    movl $0, -24(%ebp)
    
    et_for1:
        
        mov -16(%ebp), %eax  // 取循环变量i
        mov 20(%ebp), %ecx   // 取n的值
        cmp %ecx, %eax       // 比较i和n,判断i >=n
        jge final            // 若i >=n,退出外层循环
        movl $0, -20(%ebp)
            et_for2:
                
                mov -20(%ebp), %eax  // 取循环变量j
                mov 20(%ebp), %ecx   // 取n的值
                cmp %ecx, %eax       // 比较j和n,判断j >=n
                jge cont_for2        // 若j >=n,退出中层循环
                movl $0, -24(%ebp)
                    et_for3:
                        mov -24(%ebp), %eax  // 取循环变量k
                        mov 20(%ebp), %ecx   // 取n的值
                        cmp %ecx, %eax       // 比较k和n,判断k >=n
                        jge cont_for3        // 若k >=n,退出内层循环
                        
                        //mres[i][j]=m1[i][k]*m2[k][j]
                        lea 8(%ebp), %edi
                        lea 12(%ebp), %esi
                        //ecx=i*n+k, ecx= indicele pt m1
                        mov -16(%ebp), %eax
                        xorl %edx, %edx
                        mull 20(%ebp)
                        addl -24(%ebp), %eax
                        mov %eax, %ecx
                        //eax=k*n+j, eax= indicele pt m2
                        mov -24(%ebp) , %eax
                        xorl %edx, %edx
                        mull 20(%ebp)
                        addl -20(%ebp), %eax
                        
                        //ecx = produsul termenilor
                        mov (%edi, %ecx, 4), %ebx
                        mov %ebx, -28(%ebp)
                        mov (%esi, %eax, 4), %ebx
                        mov %ebx, -32(%ebp)
                        mov -28(%ebp), %eax
                        xorl %edx, %edx
                        mull -32(%ebp)
                        mov %eax, %ecx
                        
                        //eax=i*n+j
                        movl -16(%ebp), %eax
                        xorl %edx, %edx
                        mull 20(%ebp)
                        movl -20(%ebp), %ebx
                        addl %ebx, %eax
                        //ecx= prod term + mres[i][j]
                        lea 16(%ebp), %edi
                        movl (%edi, %eax, 4), %ebx
                        movl %ebx, -28(%ebp)
                        addl -28(%ebp), %ecx
                        
                        movl %ecx, (%edi, %eax, 4)
                    
                    mov -24(%ebp), %ebx
                    incl %ebx
                    mov %ebx, -24(%ebp) 
                    //k++
                    jmp et_for3
            cont_for3:
                
            mov -20(%ebp), %ebx
            incl %ebx
            mov %ebx, -20(%ebp) 
            mov $0, -24(%ebp)
            //j++ si k=0
            jmp et_for2 
                    
    
    cont_for2:
    
        
    mov -16(%ebp), %ebx
    incl %ebx
    mov %ebx, -16(%ebp) 
    //i++
    jmp et_for1
    
    final:
        addl $20, %esp
        popl %ebx
        popl %esi
        popl %edi
        popl %ebp
        ret

修复说明

  • 把局部变量分配的subl $12, %ebp和subl $8, %ebp改为subl $12, %esp和subl $8, %esp,恢复正确的栈帧结构,确保参数和局部变量的偏移计算准确。
  • 修正三层循环的cmp操作数顺序,将cmp %eax, %ecx改为cmp %ecx, %eax,配合jge实现“循环变量 >=n 时退出”的正确逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 11:05:22