MIPS Assignment - Matrix Multiply Part 1: Write a program that inputs a 4x4 matr
ID: 3848893 • Letter: M
Question
MIPS Assignment - Matrix Multiply
Part 1:
Write a program that inputs a 4x4 matrix of single-digit integers one row at a time (one row per input line – not one number per line!) and stores it into a linear 32-bit Integer Array M (so called Row-Major order). It is not completely trivial to do this given the Syscalls available and the desired input format. Hint: Format conversion will be required (do not use syscalls for the format conversion, just use loads, math, and stores).
Print the matrix back out with each row on a separate line and the values separated by spaces.Make this program a procedure so that you can use it again in later labs. For now, you can call it from a very simple main routine that just calls the routine.When you run the program, the input should look something like
Input row 1: 1 4 3 2
Input row 2: 5 7 6 8
Input row 3: 9 1 2 3
Input row 4: 4 5 6 7
Where the integers 1 2 3 4 … 8 9 or whatever matrix values the user wants to input are input by the user on the “console.”
And the output will look like
Row 1: 1 4 3 2
Row 2: 5 7 6 8
Row 3: 9 1 2 3
Row 4: 4 5 6 7
Part 2 :
First, recall how matrices are multiplied. http://www.mathsisfun.com/algebra/matrix-multiplying.html
Given the 32x32 matrices:
C code:
void mm (double x[][], double y[][], double z[][]) {
int i, j, k;
for (i = 0; i! = 32; i = i + 1)
for (j = 0; j! = 32; j = j + 1)
for (k = 0; k! = 32; k = k + 1)
x[i][j] = x[i][j]+ y[i][k] * z[k][j];
}
Addresses of x, y, z in $a0, $a1, $a2, and i, j, k in $s0, $s1, $s2
MIPS code:
li $t1, 32 # $t1 = 32 (row size/loop end)
li $s0, 0 # i = 0; initialize 1st for loop
L1: li $s1, 0 # j = 0; restart 2nd for loop
L2: li $s2, 0 # k = 0; restart 3rd for loop
sll $t2, $s0, 5 # $t2 = i * 32 (size of row of x)
addu $t2, $t2, $s1 # $t2 = i * size(row) + j
sll $t2, $t2, 3 # $t2 = byte offset of [i][j]
addu $t2, $a0, $t2 # $t2 = byte address of x[i][j]
l.d $f4, 0($t2) # $f4 = 8 bytes of x[i][j]
L3: sll $t0, $s2, 5 # $t0 = k * 32 (size of row of z)
addu $t0, $t0, $s1 # $t0 = k * size(row) + j
sll $t0, $t0, 3 # $t0 = byte offset of [k][j]
addu $t0, $a2, $t0 # $t0 = byte address of z[k][j]
l.d $f16, 0($t0) # $f16 = 8 bytes of z[k][j]
sll $t0, $s0, 5 # $t0 = i*32 (size of row of y)
addu $t0, $t0, $s2 # $t0 = i*size(row) + k
sll $t0, $t0, 3 # $t0 = byte offset of [i][k]
addu $t0, $a1, $t0 # $t0 = byte address of y[i][k]
l.d $f18, 0($t0) # $f18 = 8 bytes of y[i][k]
mul.d $f16, $f18, $f16 # $f16 = y[i][k] * z[k][j]
add.d $f4, $f4, $f16 # f4=x[i][j] + y[i][k]*z[k][j]
addiu $s2, $s2, 1 # $k k + 1
bne $s2, $t1, L3 # if (k != 32) go to L3
s.d $f4, 0($t2) # x[i][j] = $f4
addiu $s1, $s1, 1 # $j = j + 1
bne $s1, $t1, L2 # if (j != 32) go to L2
addiu $s0, $s0, 1 # $i = i + 1
bne $s0, $t1, L1 # if (i != 32) go to L1
Now, convert the matrix multiply to a program that multiplies 4x4 integer matrices instead of 32x32 floating-point matrices (replace all the floating-pointloads, stores, and operations with their integer equivalents, e.g., l.d becomes lw etc.).Modify your program from Part 1 that reads in a 4x4 integer matrix to allow the user toinput two 4x4 matrices by row, then multiply the integer matrices and print out the results by row.
Explanation / Answer
Part 1:
Coding: MIPS
.file "main.c"
.section .rodata
.LC0:
.string "Input row %d: "
.LC1:
.string "%d"
.LC2:
.string " Row %d:"
.LC3:
.string " %d"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $80, %rsp
movl $0, -4(%rbp)
jmp .L2
.L4:
movl -4(%rbp), %eax
andl $3, %eax
testl %eax, %eax
jne .L3
movl -4(%rbp), %eax
leal 3(%rax), %edx
testl %eax, %eax
cmovs %edx, %eax
sarl $2, %eax
addl $1, %eax
movl %eax, %esi
movl $.LC0, %edi
movl $0, %eax
call printf
.L3:
leaq -80(%rbp), %rax
movl -4(%rbp), %edx
movslq %edx, %rdx
salq $2, %rdx
addq %rdx, %rax
movq %rax, %rsi
movl $.LC1, %edi
movl $0, %eax
call __isoc99_scanf
addl $1, -4(%rbp)
.L2:
cmpl $15, -4(%rbp)
jle .L4
movl $0, -4(%rbp)
jmp .L5
.L7:
movl -4(%rbp), %eax
andl $3, %eax
testl %eax, %eax
jne .L6
movl -4(%rbp), %eax
leal 3(%rax), %edx
testl %eax, %eax
cmovs %edx, %eax
sarl $2, %eax
addl $1, %eax
movl %eax, %esi
movl $.LC2, %edi
movl $0, %eax
call printf
.L6:
movl -4(%rbp), %eax
cltq
movl -80(%rbp,%rax,4), %eax
movl %eax, %esi
movl $.LC3, %edi
movl $0, %eax
call printf
addl $1, -4(%rbp)
.L5:
cmpl $15, -4(%rbp)
jle .L7
movl $10, %edi
call putchar
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (GNU) 4.8.5 20150623 (Red Hat 4.8.5-4)"
.section .note.GNU-stack,"",@progbits
Coding: C
#include <stdio.h>
int main()
{
int array[4*4];
int i;
for (i=0; i<16; i++) {
if (i%4 == 0) printf ("Input row %d: ", (i/4)+1);
scanf("%d", &array[i]);
}
for (i=0; i<16; i++) {
if (i%4 == 0) printf (" Row %d:", (i/4)+1);
printf(" %d", array[i]);
}
printf(" ");
}
Related Questions
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.