我的emu8086矩阵乘法代码为何无法输出预期结果?
EMU8086矩阵乘法与标量乘法代码错误排查与修正
核心错误分析
1. 矩阵乘法索引逻辑混乱
- 原代码中
mov bx, b[si]将B矩阵的元素值存入bx,后续却用c[bx]作为结果矩阵C的索引,这会导致索引完全错误(bx存储的是数值而非偏移量)。 - 矩阵乘法的行列遍历逻辑错误:3x3矩阵乘法中,每个结果元素
c[row][col]需要计算A的第row行与B的第col列对应元素的乘积和。原代码的di、si移动未实现行列的正确对应,且外层循环用错误的变量判断终止条件。
2. 数值转ASCII方式错误
- 原代码直接给结果加48转换为ASCII,仅适用于0-9的个位数,但矩阵乘法结果(如30、60等)是多位数,直接转换会输出乱码或符号,必须实现多位数打印逻辑。
3. 标量乘法指令使用错误
- 原代码的
multiply_scalar_loop循环内,第一次执行mul c[di]后ax的值变为乘积,后续循环会用这个乘积继续乘下一个元素,而非原始的scalar值,每次循环前需重新加载scalar到ax。
修正后的代码
.model small .stack 100h .data a dw 1, 2, 3, 4, 5, 6, 7, 8, 9 ; 3x3矩阵A b dw 9, 8, 7, 6, 5, 4, 3, 2, 1 ; 3x3矩阵B c dw 9 dup(0) ; 结果矩阵C scalar dw 2 newline db 13, 10, '$' ; 换行符 .code mov ax, @data mov ds, ax ; 矩阵乘法: C = A * B mov cx, 3 ; 外层循环: A的行数(3行) mov di, 0 ; A的行索引偏移(每次+6,一行3个元素,每个占2字节) matrix_row_loop: push cx ; 保存外层循环计数器 mov cx, 3 ; 中层循环: B的列数(3列) mov si, 0 ; B的列索引偏移(每次+2,一列3个元素,每个占2字节) matrix_col_loop: push cx ; 保存中层循环计数器 mov cx, 3 ; 内层循环: 行列元素的乘积次数(3次) mov bx, 0 ; 临时存储当前元素的乘积和 mov bp, di ; 临时保存A的当前行起始偏移 mov dx, si ; 临时保存B的当前列起始偏移 inner_mul_loop: mov ax, a[bp] mul b[dx] add bx, ax ; 累加乘积和 add bp, 2 ; 移动到A的下一个元素(同列) add dx, 6 ; 移动到B的下一个元素(同行,下一行的同列) loop inner_mul_loop ; 将结果存入C的对应位置: C[row][col] = bx mov ax, di ; 计算C的行偏移 shr ax, 1 ; 转为元素索引(每个元素2字节) mov dx, si ; 计算C的列偏移 shr dx, 1 mov cx, 3 mul cx ; row * 3 add ax, dx ; row*3 + col = 线性索引 shl ax, 1 ; 转为字节偏移 mov c[ax], bx pop cx ; 恢复中层循环计数器 add si, 2 ; 移动到B的下一列 loop matrix_col_loop pop cx ; 恢复外层循环计数器 add di, 6 ; 移动到A的下一行 loop matrix_row_loop ; 打印矩阵乘法结果 mov ah, 09h lea dx, newline int 21h call print_matrix ; 标量乘法: C = C * scalar mov cx, 9 mov di, 0 scalar_mul_loop: mov ax, c[di] mul scalar mov c[di], ax add di, 2 loop scalar_mul_loop ; 打印标量乘法结果 mov ah, 09h lea dx, newline int 21h call print_matrix ; 退出程序 mov ax, 4C00h int 21h ; 打印3x3矩阵的子程序 print_matrix proc mov cx, 3 ; 行数 mov di, 0 print_row: push cx mov cx, 3 ; 列数 print_col: mov ax, c[di] call print_number ; 打印当前数字 mov ah, 02h mov dl, ' ' ; 元素间加空格 int 21h add di, 2 loop print_col pop cx mov ah, 09h lea dx, newline int 21h loop print_row ret print_matrix endp ; 打印16位无符号数的子程序 print_number proc push bx push cx push dx mov cx, 0 ; 计数数字的位数 mov bx, 10 number_divide: xor dx, dx div bx ; ax = ax / 10, dx = ax % 10 push dx ; 保存余数 inc cx cmp ax, 0 jne number_divide number_print: pop dx add dl, 48 ; 转为ASCII mov ah, 02h int 21h loop number_print pop dx pop cx pop bx ret print_number endp end
修正说明
- 矩阵乘法:重新设计三层循环,分别遍历A的行、B的列及对应元素,正确计算乘积和并存入C的对应位置。
- 打印模块:新增
print_number子程序处理多位数ASCII转换,print_matrix子程序按3x3格式打印矩阵,提升可读性。 - 标量乘法:每次循环重新加载当前矩阵元素到ax,与scalar相乘,确保计算逻辑正确。
内容的提问来源于stack exchange,提问作者Tamara Spasojevic
相关产品推荐
相关产品推荐

