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

如何输入两个n*n矩阵并实现乘法?汇编代码报错求助

汇编中动态定义矩阵并实现输入的解决方案

你的代码错误原因

times是汇编器的编译时伪指令,它要求参数必须是编译阶段就能确定的常量。你代码里的n是运行时才会从输入获取值的变量(初始值1只是占位),汇编器在编译时无法知道n的最终大小,所以会报错。

正确的实现思路

因为矩阵大小n是运行时动态确定的,不能在.data段静态定义,必须用动态内存分配,或者在栈上预留空间(栈空间有限,适合小n场景)。下面以Linux下NASM汇编结合C标准库为例,给出完整实现步骤:

核心步骤

  • 获取n的值:通过scanf读取用户输入的整数n,存入内存变量。
  • 动态分配内存:调用C库malloc函数,为两个n*n矩阵和结果矩阵分配空间(每个单精度浮点数占4字节,所以每个矩阵需n*n*4字节)。
  • 输入矩阵元素:用嵌套循环遍历矩阵的行和列,逐个调用scanf读取元素。
  • 执行矩阵乘法:通过三层嵌套循环实现行×列的累加运算,用x87浮点指令处理单精度数值。
  • 释放内存:调用free回收动态分配的内存,避免泄漏。

示例代码

extern printf, scanf, malloc, free

section .data
    input_n_fmt: db "%d", 0
    input_float_fmt: db "%f", 0
    output_fmt: db "Result matrix[%d][%d] = %f", 10, 0

section .bss
    n: resd 1          ; 存储n的值
    mat1: resd 1       ; 第一个矩阵的指针
    mat2: resd 1       ; 第二个矩阵的指针
    result: resd 1     ; 结果矩阵的指针

section .text
    global main

main:
    ; 读取n的值
    push n
    push input_n_fmt
    call scanf
    add esp, 8

    ; 计算单个矩阵的内存大小:n*n*4字节
    mov eax, [n]
    mul eax            ; eax = n*n
    mov ebx, 4
    mul ebx            ; eax = n*n*4

    ; 分配第一个矩阵内存
    push eax
    call malloc
    add esp, 4
    mov [mat1], eax

    ; 分配第二个矩阵内存
    push eax
    call malloc
    add esp, 4
    mov [mat2], eax

    ; 分配结果矩阵内存
    push eax
    call malloc
    add esp, 4
    mov [result], eax

    ; 输入第一个矩阵
    push dword [mat1]
    push dword [n]
    call input_matrix
    add esp, 8

    ; 输入第二个矩阵
    push dword [mat2]
    push dword [n]
    call input_matrix
    add esp, 8

    ; 执行矩阵乘法
    push dword [result]
    push dword [mat2]
    push dword [mat1]
    push dword [n]
    call multiply_matrices
    add esp, 16

    ; 打印结果矩阵
    push dword [result]
    push dword [n]
    call print_matrix
    add esp, 8

    ; 释放内存
    push dword [mat1]
    call free
    add esp, 4
    push dword [mat2]
    call free
    add esp, 4
    push dword [result]
    call free
    add esp, 4

    ; 退出程序
    mov eax, 0
    ret

; 输入矩阵函数:参数1为n,参数2为矩阵指针
input_matrix:
    push ebp
    mov ebp, esp
    mov ecx, [ebp+8]   ; ecx = n
    mov esi, [ebp+12]  ; esi = 矩阵指针
    xor edi, edi       ; 行索引i

input_row_loop:
    cmp edi, ecx
    jge input_done
    xor ebx, ebx       ; 列索引j

input_col_loop:
    cmp ebx, ecx
    jge input_next_row

    ; 计算当前元素地址:esi + (i*n + j)*4
    mov eax, edi
    mul ecx
    add eax, ebx
    mov edx, 4
    mul edx
    add eax, esi

    ; 读取浮点数到当前元素
    push eax
    push input_float_fmt
    call scanf
    add esp, 8

    inc ebx
    jmp input_col_loop

input_next_row:
    inc edi
    jmp input_row_loop

input_done:
    pop ebp
    ret

; 矩阵乘法函数:参数1为n,参数2为mat1,参数3为mat2,参数4为result
multiply_matrices:
    push ebp
    mov ebp, esp
    mov ecx, [ebp+8]   ; ecx = n
    mov esi, [ebp+12]  ; esi = mat1
    mov edi, [ebp+16]  ; edi = mat2
    mov edx, [ebp+20]  ; edx = result
    xor eax, eax       ; 行索引i

mul_row_loop:
    cmp eax, ecx
    jge mul_done
    xor ebx, ebx       ; 列索引j

mul_col_loop:
    cmp ebx, ecx
    jge mul_next_row
    xor ecx, ecx       ; 累加索引k
    fldz               ; 初始化累加器为0.0

mul_accum_loop:
    cmp ecx, [ebp+8]
    jge mul_store_result

    ; 加载mat1[i][k]
    mov eax, [ebp+8]
    mul ecx
    add eax, ebx
    mov edx, 4
    mul edx
    add eax, esi
    fld dword [eax]

    ; 加载mat2[k][j]并相乘
    mov eax, [ebp+8]
    mul ebx
    add eax, ecx
    mov edx, 4
    mul edx
    add eax, edi
    fmul dword [eax]
    faddp st1, st0     ; 累加到总和

    inc ecx
    jmp mul_accum_loop

mul_store_result:
    ; 存储结果到result[i][j]
    mov eax, [ebp+8]
    mul ebx
    add eax, [ebp+8]
    mov edx, 4
    mul edx
    add eax, edx
    fstp dword [eax]

    inc ebx
    jmp mul_col_loop

mul_next_row:
    inc eax
    jmp mul_row_loop

mul_done:
    pop ebp
    ret

; 打印矩阵函数:参数1为n,参数2为矩阵指针
print_matrix:
    push ebp
    mov ebp, esp
    mov ecx, [ebp+8]   ; ecx = n
    mov esi, [ebp+12]  ; esi = 矩阵指针
    xor edi, edi       ; 行索引i

print_row_loop:
    cmp edi, ecx
    jge print_done
    xor ebx, ebx       ; 列索引j

print_col_loop:
    cmp ebx, ecx
    jge print_next_row

    ; 计算当前元素地址
    mov eax, edi
    mul ecx
    add eax, ebx
    mov edx, 4
    mul edx
    add eax, esi

    ; 打印元素(转成double适配printf的%f)
    push dword [eax+3]
    push dword [eax]
    push ebx
    push edi
    push output_fmt
    call printf
    add esp, 20

    inc ebx
    jmp print_col_loop

print_next_row:
    inc edi
    jmp print_row_loop

print_done:
    pop ebp
    ret

关键注意事项

  • 若是使用MASM汇编,语法会有差异(比如用invoke替代call),但动态分配内存的核心逻辑一致。
  • 小n场景可直接在栈上预留空间(如sub esp, n*n*4),但大n建议用malloc或系统调用brk避免栈溢出。
  • 矩阵乘法可通过SSE指令集优化单精度浮点数的运算效率,适合64位汇编场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 18:19:52