Mars MIPS 3x3矩阵乘法:将C语言循环代码转换为MIPS汇编
Got it, let's break down how to translate your C matrix multiplication code into MIPS assembly that works with the MARS simulator. Since we're dealing with a fixed 3x3 matrix, we can hardcode DIM = 3 to simplify the logic—no need for a variable, which makes the assembly cleaner and faster.
First: Data Section Setup
We'll define our three matrices (a, b, r) in the .data segment. I'll add sample values for a and b so you can test the code, and reserve space for r (we'll initialize its values to 0 in the code as your C snippet does).
.data # 3x3 matrix A (sample values) a: .word 1, 2, 3 .word 4, 5, 6 .word 7, 8, 9 # 3x3 matrix B (sample values) b: .word 10, 11, 12 .word 13, 14, 15 .word 16, 17, 18 # 3x3 result matrix R (initialized to 0 later) r: .word 0, 0, 0 .word 0, 0, 0 .word 0, 0, 0 dim: .word 3 # Hardcoded DIM = 3 (optional, but makes code readable) newline: .asciiz "\n" space: .asciiz " "
Second: Text Section (Main Logic)
This is where we'll implement the three nested loops from your C code. We'll use saved registers ($s0-$s6) to hold loop counters and indices, since they preserve values across function calls (though we're not using functions here, it's good practice).
.text .globl main main: # Initialize saved registers (save old values first, though main doesn't need it for MARS) addi $sp, $sp, -28 # Allocate stack space for 7 saved registers sw $s0, 0($sp) sw $s1, 4($sp) sw $s2, 8($sp) sw $s3, 12($sp) sw $s4, 16($sp) sw $s5, 20($sp) sw $s6, 24($sp) lw $s3, dim # $s3 = DIM = 3 li $s0, 0 # int i = 0; (outer loop counter) outer_loop: bge $s0, $s3, end_outer_loop # if i >= 3, exit outer loop li $s1, 0 # int j = 0; (middle loop counter) middle_loop: bge $s1, $s3, end_middle_loop # if j >=3, exit middle loop # Calculate ri = i * DIM + j mul $t0, $s0, $s3 # $t0 = i*3 add $s4, $t0, $s1 # $s4 = ri = i*3 +j # r[ri] = 0; la $t1, r # $t1 = address of r sll $t2, $s4, 2 # $t2 = ri *4 (since each word is 4 bytes) add $t3, $t1, $t2 # $t3 = &r[ri] sw $zero, 0($t3) # r[ri] = 0 li $s2, 0 # int k =0; (inner loop counter) inner_loop: bge $s2, $s3, end_inner_loop # if k >=3, exit inner loop # Calculate ai = i*DIM +k mul $t0, $s0, $s3 add $s5, $t0, $s2 # $s5 = ai # Calculate bi = k*DIM +j mul $t0, $s2, $s3 add $s6, $t0, $s1 # $s6 = bi # Load a[ai] and b[bi] la $t1, a sll $t2, $s5, 2 add $t3, $t1, $t2 lw $t4, 0($t3) # $t4 = a[ai] la $t1, b sll $t2, $s6, 2 add $t3, $t1, $t2 lw $t5, 0($t3) # $t5 = b[bi] # Multiply a[ai] * b[bi] mul $t6, $t4, $t5 # $t6 = a[ai] * b[bi] # Load current r[ri] value, add product, store back la $t1, r sll $t2, $s4, 2 add $t3, $t1, $t2 lw $t7, 0($t3) # $t7 = r[ri] add $t7, $t7, $t6 # $t7 = r[ri] + product sw $t7, 0($t3) # r[ri] = updated value addi $s2, $s2, 1 # k++ j inner_loop end_inner_loop: addi $s1, $s1, 1 # j++ j middle_loop end_middle_loop: addi $s0, $s0, 1 # i++ j outer_loop end_outer_loop: # Optional: Print the result matrix r to verify jal print_matrix # Restore saved registers lw $s0, 0($sp) lw $s1, 4($sp) lw $s2, 8($sp) lw $s3, 12($sp) lw $s4, 16($sp) lw $s5, 20($sp) lw $s6, 24($sp) addi $sp, $sp, 28 # Exit program li $v0, 10 syscall # Helper function to print the 3x3 matrix print_matrix: li $t0, 0 # row counter =0 print_row: bge $t0, $s3, end_print li $t1, 0 # column counter=0 print_col: bge $t1, $s3, end_col # Calculate index = t0*3 +t1 mul $t2, $t0, $s3 add $t2, $t2, $t1 sll $t2, $t2, 2 la $t3, r add $t3, $t3, $t2 lw $a0, 0($t3) li $v0, 1 syscall # print element # Print space la $a0, space li $v0, 4 syscall addi $t1, $t1,1 j print_col end_col: # Print newline la $a0, newline li $v0,4 syscall addi $t0, $t0,1 j print_row end_print: jr $ra
Key Notes to Match Your C Code
- Loop Counters:
$s0=i,$s1=j,$s2=k—directly maps to your C loop variables. - Index Calculation: We use
mulfor integer multiplication (MARS supports this; alternatively, you could usesll+addfor*3since 3=2+1, butmulis more readable). - Array Access: Since MIPS uses byte addressing, we multiply indices by 4 (
sll $t2, $s4, 2) to get the correct byte offset for word-sized elements. - Initialization: We explicitly set
r[ri] =0before the inner loop, just like your C code does.
Testing the Code
When you run this in MARS, it will compute the product of matrices a and b, then print the result matrix. For the sample values I used, the result should be:
84 90 96 201 216 231 318 342 366
内容的提问来源于stack exchange,提问作者Cruzhn

