如何输入两个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
相关产品推荐
相关产品推荐

