[![hackmd-github-sync-badge](https://hackmd.io/T5bREbZJQzSz-tSkw9gbUw/badge)](https://hackmd.io/T5bREbZJQzSz-tSkw9gbUw) # MIPS Note ###### tags: `School` #### [TOC] --- ## [MIPS指令集](https://blog.xuite.net/tzeng015/twblog/113272086-MIPS+%E6%8C%87%E4%BB%A4%E9%9B%86) ### Compare * j: jump,跳轉到指定位址。<br> jr: jump register,跳轉到暫存器存放的位址。<br> jal: jump and link,跳轉到指定位址**並保存返回位址**。 * lw: load word,memory->register<br> sw: store word,register->memory ![](https://i.imgur.com/aGiZp8o.png) --- ### 常用暫存器 | 名稱 | 編號 | 用途 | | -------- | -------- | -------- | | $s0 ~ $s7 | 16 ~ 23 | 保留暫存器 | | $t0 ~ $t7 | 8 ~ 15 | 臨時暫存器 | | $v0 ~ $v1 | 2 ~ 3 | 傳回值暫存器 | | $a0 ~ $a3 | 4 ~ 7 | 參數暫存器 | | $sp | 29 | 堆疊指標 | | $ra | 31 | 程式返回位置 | --- ## caller & callee ![](https://i.imgur.com/mUGf9Fm.png) ![](https://i.imgur.com/KlCfeab.png) ![](https://i.imgur.com/M2DzR6X.png) --- ## QA ### j, jr, jal這三個跳轉指令有什麼區別? - j: jump - 無條件跳轉到一個指定的位址,語法為`j target` (target表示跳轉的目標位址) - jr: jump register - 跳轉到一個暫存器所存放的位址,語法為`jr $s` ($s表示一個存儲跳轉目標位址的暫存器) - jal: jump and link - 跳轉到一個指定的位址並保存返回地址,語法為`jal target` - j指令和jr指令只是用來**跳轉到指定位址或暫存器存放的位址**,**不保存返回地址**,而jal指令則在跳轉之前會**將返回地址存入$ra($31)暫存器中**,以便後續指令執行完畢後返回。 - Ex. ```assemble .data words: .asciiz "Result\n" .text .globl main main: jal printResult #跑到printResult標籤 printResult: li $v0, 4 #輸出 la $a0, words syscall j endPrintResult #跳到endPrintResult endPrintResult: jr $ra #跳回去上個用到jal的位址 #(因為jal會儲存位址在$ra) ``` --- ## Example ### 1. caller & callee ```cpp sum = leaf_example(a,b,c,d) int leaf_example (int g, h, i, j) { int f; f = (g + h) - (i + j); return f; } ``` * return address: `$ra` * procedure address: Label * arguments(`g, ..., j`): `$a0, ..., $a3` * local variable: $s0, \$s1, ... (`f` in `$s0`) **(hence, need to save $s0 on stack)** * save `$t0` and `$t1` * return value: `$v0` ```assembly leaf_example: # 配置記憶體(stack) addi $sp, $sp, -12 sw $s0, 0($sp) # f(return) sw $t0, 4($sp) sw $t1, 8($sp) # 主要程式 add $t0, $a0, $a1 # $t0=g+h add $t1, $a2, $a3 # $t1=i+j sub $s0, $t0, $t1 # f=(g+h)-(i+j) add $v0, $s0, $zero # f的值給$v0(傳回值暫存器) #歸還記憶體 lw $s0, 0($sp) lw $t0, 4($sp) lw $t1, 8($sp) addi $sp, $sp, 12 jr $ra # return ``` ### 2. recrusive -- factorial ```cpp int fact(int n) { if (n < 1) { return f; } else { return n * fact(n - 1); } } ``` * argument `n` in `$a0` * result in `$v0` ![](https://i.imgur.com/KtstIlL.png) ### 3. array ![](https://i.imgur.com/Pt5ACXN.png) ### 4. while loop ```cpp while (save[i] == k) { i += 1; } ``` * `i` in `$s3`, `k` in `$s5`, addr. of `save` in `$s6` ```assembly Loop: sll $t1, $s3, 2 #$t1=i x 4 add $t1, $t1, $s6 #$t1=addr of save[i] lw $t0, 0($t1) #$t0=save[i] bne $t0, $s5, Exit #if save[i]!=k goto Exit addi $s3, $s3, 1 #i=i+1 j Loop #goto Loop Exit: … ``` --- ## Exercise ### C to MIPS 填空格 ![](https://i.imgur.com/Ig9h0qW.png) #### 完全不一樣版(chatGPT) ```assembly .data x: .word 10 y: .word 0 msg: .asciiz "%d\n" .text .globl main main: # 載入x的值到$t0 lw $t0, x # 載入y的值到$t1 lw $t1, y # 比較x和y的值 slt $t2, $t0, $t1 # 如果x<y,跳轉到label1 beq $t2, $1, label1 # 如果x>=y,執行else區塊,y = y - 2 addi $t1, $t1, -2 # 將修改後的y的值存回y sw $t1, y # 跳轉到label2 j label2 label1: # 如果x<y,執行if區塊,x = x + 2 addi $t0, $t0, 2 # 將修改後的x的值存回x sw $t0, x label2: # 將x的值載入$a0 lw $a0, x # 印出x的值 li $v0, 1 la $a1, msg syscall # 程式結束 li $v0, 10 syscall ``` * .word和.asciiz有什麼差別? - .word 指令用來聲明一個或多個32位元的變數。例如,.word 10 會在資料區塊中聲明一個名為 10 的變數,該變數的值為 10。在MIPS組譯器執行程式碼時,可以使用 lw 指令讀取 .word 指令聲明的變數的值,例如:lw $t0, 10 會將 10 中的值載入到 $t0 寄存器中。 - .asciiz 指令用來聲明一個以 NULL 結尾的 ASCII 字符串。例如,.asciiz "Hello, World!" 會在資料區塊中聲明一個包含 "Hello, World!" 字符串的變數,該變數會以 NULL 結尾。在MIPS組譯器執行程式碼時,可以使用 la 指令將 .asciiz 指令聲明的變數的地址載入到 $t0 寄存器中,例如:la $t0, mystring 會將 mystring 變數的地址載入到 $t0 寄存器中。同時,可以使用 li 和 syscall 指令印出這個字串,例如:li $v0, 4; syscall 會將字串印出到終端。 - 總體而言,.word 指令用來聲明數值型的變數,而 .asciiz 指令用來聲明字符型的變數,並且需要以 NULL 結尾。 * `.text .globl main`是什麼意思? - .text 是MIPS指令中的一個區塊,用於存放程式碼。在這個區塊中,可以聲明和定義各種MIPS指令,例如 add、lw、sw、beq 等等。在MIPS組譯器執行程式碼時,會從這個區塊中讀取指令並且執行。 - .globl 則是一個指令,用於告訴組譯器這個符號(symbol)是一個全域符號(global symbol),可以被其他程式碼引用。在這個程式碼中,.globl main 則是聲明了一個名為 main 的全域符號,表示這是這個程式碼的入口點(entry point),也就是程式碼執行時的起點。在MIPS組譯器執行程式碼時,會將 main 函數的地址作為程式碼的入口點。 * `j label2`是什麼意思? - j label2 是MIPS指令中的一個無條件跳轉指令,用於將程式的執行轉移到指定的標籤(label)所在的指令地址。這個指令將會將 PC 設置為指定標籤所在的指令地址,然後程序將會從該指令地址繼續執行。 - 在 j label2 中,label2 是一個在程式碼中定義的標籤(label),它通常會被放置在程式碼中的某個位置,例如: ```assembly loop: # 處理循環中的程式碼 j loop # 無條件跳轉回 loop 標籤處繼續執行 ``` - 在上面的例子中,loop 是一個標籤,它標記了程式碼中一個循環的開始位置。當程式碼執行到 j loop 時,將會無條件跳轉到 loop 標籤處繼續執行循環中的程式碼。 #### 填空格版 ```assembly main: # int x=10, y=0 addi $s0, $zero, 10 # 將 x 設為 10 addi $s1, $zero, 0 # 將 y 設為 0 #if(x<y), $t0=1, [else $t0=0] slt $t0, $s0, $s1 # 比較 x 和 y 的大小,若 x<y 則 $t0 為 1,否則為 0 #"if $t0=0, execute else" beq $t0, $zero, else # 若 $t0 為 0,則*跳轉*至 else 標籤 then: addi $s0, $s0, 2 # x = x + 2 j exit # *跳轉*至 exit 標籤,結束程式 else: addi $s1, $s1, -2 # y = y - 2 exit: li $v0, 1 # 將系統調用碼設為 1,表示輸出整數 move $a0, $s0 # 將 x 設為輸出參數 syscall # 系統調用,輸出 x li $v0, 10 # 將系統調用碼設為 10,表示結束程式 syscall # 系統調用,結束程式 ``` * `$zero`是什麼意思? - 在 MIPS 組合語言中,\$zero 是一個特殊的暫存器,其值永遠都是 0,不論何時何地,都不會被改變。因此,\$zero 暫存器通常被用來當作常數 0 的參考,或是在某些操作中作為暫存器使用。例如: - addi \$t0, \$zero, 10:將 10 存放到 \$t0 暫存器中。 - add \$t0, \$t1, \$zero:將 \$t1 暫存器中的值加上 0,並存放到 \$t0 暫存器中。 - 由於 \$zero 暫存器永遠都是 0,因此在某些操作中,可以省略對 $zero 暫存器的引用,例如 addi \$t0, \$zero, 0 可以簡寫成 addi \$t0, \$0, 0。 * `move $a0, $s0`是什麼意思? - 在 MIPS 組合語言中,move $a0, $s0 是一條指令,其目的是將 $s0 暫存器中的值複製到 $a0 暫存器中,而不是像 add 或 sub 這樣進行運算。這條指令的作用通常是將某個暫存器的值傳遞給系統調用的參數,以供系統調用使用。 - 在這個指令中,$s0 可以是任意一個暫存器,而 $a0 則通常是系統調用的參數之一,例如 syscall 中的系統碼參數。因此,這條指令可以用來準備系統調用的參數,讓系統調用能夠正確地執行。 --- ## Homework ### BMI Calculator ```cpp #include <stdlib.h> #include <stdio.h> int calculateBMI(int height, int weight) { int bmi = (weight * 10000) / (height * height); return bmi; } void printResult (int bmi) { if (bmi < 18) printf("%s", "underweight\n"); else if (bmi > 24) printf("%s", "overweight\n"); else printf("%d\n", bmi); } int main() { int height, weight, bmi; while (1) { scanf("%d", &height); if (height == -1) break; scanf("%d", &weight); bmi = calculateBMI(height, weight); printResult(bmi); } return 0; } ``` | Input | Output | | -------- | -------- | | 180<br>59<br>180<br>58<br>180<br>90<br>-1| 18<br>underweight<br>overweight| | 180<br>80<br>180<br>81<br>180<br>50<br>-1| 24<br>overweight<br>underweight| | 178<br>80<br>150<br>50<br>196<br>76<br>190<br>44<br>-1| overweight<br>22<br>19<br>underweight| #### 助教給的解答 ```assembly .data overWeight: .asciiz "overweight\n" underWeight: .asciiz "underweight\n" newLine: .asciiz "\n" .text .globl main main: while: # Get the height from the user. li $v0, 5 syscall add $s0,$v0,$zero beq $s0,-1,exitWhile # Get the weight from the user. li $v0, 5 syscall add $s1,$v0,$zero add $a0,$s0,$zero add $a1,$s1,$zero jal calculateBMI add $s2,$v0,$zero add $a1,$s2,$zero jal printResult j while exitWhile: # Tell the system that the program is done. li $v0, 10 syscall calculateBMI: sub $sp,$sp,4 sw $s0,0($sp) mul $t0,$a1,10000 mul $t1,$a0,$a0 div $s0,$t0,$t1 add $v0,$s0,$zero lw $s0,0($sp) add $sp,$sp,4 jr $ra printResult: addi $t2,$zero,0 addi $t2,$t2,18 slt $t3,$a1,$t2 beq $t3,$zero,elseIfInPrint la $a0,underWeight li $v0,4 syscall j exit elseIfInPrint: addi $t4,$zero,0 addi $t4,$t4,24 slt $t5,$t4,$a1 beq $t5,$zero,elseInPrint la $a0,overWeight li $v0,4 syscall j exit elseInPrint: add $a0,$a1,$zero li $v0,1 syscall la $a0, newLine li $v0,4 syscall exit: jr $ra ``` #### 自己寫的 ```assembly .data under: .asciiz "underweight\n" over: .asciiz "overweight\n" newline: .asciiz "\n" .text .globl loop loop: # 讀取身高 li $v0, 5 #輸入 syscall move $t0, $v0 # 將身高存入$t0 # 如果輸入-1,則跳轉到結束程序 beq $t0, -1, exit # 讀取體重 li $v0, 5 #輸入 syscall move $t1, $v0 # 將體重存入$t1 #呼叫calculateBMI jal calculateBMI move $t2, $v0 # 將計算結果存入$t2 #呼叫printResult jal printResult j loop #代表迴圈,會跳到loop那一行 # 結束 exit: li $v0, 10 #結束程序 syscall # Function to calculate BMI calculateBMI: mul $t2, $t1, 10000 # $t2=weight*10000 mul $t3, $t0, $t0 # $t3=height*height div $t2, $t2, $t3 # $t2 = (weight*10000)/(height*height) # !!!!!!!!!!! move $a0, $t2 move $v0, $t2 #把BMI存入$v0 jr $ra #讀取返回地址,並跳轉到此地址繼續執行程序 printResult: #underweight li $t0, 18 # if $a0(BMI)>=$t0(18), jump to overweight(maybe normal or overweight) bge $a0, $t0, overweight # else-> underweight li $v0, 4 #print la $a0, under syscall j endPrintResult # jr $ra #jr $ra overweight: li $t0, 24 # if $a0(BMI)<=$t0(24), jump to normal(18<=BMI<=24) ble $a0, $t0, normal li $v0, 4 #print la $a0, over syscall j endPrintResult #jr $ra normal: li $v0, 1 #印出整數 move $a0, $t2 #將計算出的BMI值復制到$t2寄存器中 syscall # 呼叫系統調用,印出BMI的值 li $v0, 4 la $a0, newline syscall j endPrintResult #jr $ra endPrintResult: jr $ra ``` --- ### Fibonacci number ```cpp #include <stdlib.h> #include <stdio.h> int fib(int n, int dp[]) { if (dp[n]!= 0) { printf("%d\n", dp[n]); return dp[n]; } if (n == 1 || n == 2) { dp[n] = 1; return 1; } else { dp[n] = fib(n-1, dp) + fib(n-2, dp); if (dp[n] % 3 ==0) printf("%d\n", dp[n]); return dp[n]; } } int main() { int data[200]; int answer = 0, num = 0, i=0; for (i=0; i<200; i++) data[i]=0; scanf("%d", &num); answer = fib(num, data); printf("%d\n ", answer); return 0; } ``` | Input | Output | | -------- | -------- | | 8| 1<br>3<br>2<br>3<br>5<br>8<br>21<br>21| | 2| 1| | 13| 1<br>3<br>2<br>3<br>5<br>8<br>21<br>13<br>21<br>34<br>55<br>144<br>89<br>233| #### 助教給的解答 ```assembly .data myArray: .space 800 newLine: .asciiz "\n" .text .globl main main: add $s0,$zero, $0 #answer = 0 add $s1,$zero,$zero #num = 0 li $s3,0 # i = 0 la $s4,myArray #data[200] forInMain: slti $at,$s3,200 beq $at,$zero,exitForInMain sll $t0,$s3,2 add $t0,$t0,$s4 sw $zero,0($t0) addi $s3,$s3,1 j forInMain exitForInMain: # Read the number from the user. li $v0, 5 syscall add $s1,$v0,$0 # Call the factorial function add $a0,$s1,$0 add $s1,$v0,$0 add $a1,$s4,$0 jal fib add $s0,$v0,$0 # Display the results li $v0, 1 add $a0,$s0,$0 syscall la $a0,newLine li $v0,4 syscall # Tell the system that the program is done. li $v0, 10 syscall fib: sub $sp, $sp, 12 sw $ra, 0($sp) sw $s0, 4($sp) sw $s1, 8($sp) add $s0,$a0,$0 # Base Case: already have value in myArray sll $t0,$s0,2 add $t0,$t0, $a1 lw $t0, 0( $t0) beqz $t0, L1 li $v0, 1 add $a0,$t0,$0 syscall la $a0,newLine li $v0,4 syscall add $v0,$t0,$0 j fibDone L1: # Base Case: parameter is 1 or 2 beq $s0, 1, skip li $t0, 1 j end skip: li $t0, 0 end: beq $s0, 2, skip2 li $t1, 1 j end2 skip2: li $t1, 0 end2: and $t0, $t0, $t1 beq $t0,1,L2 sll $t0,$s0,2 add $t0,$t0, $a1 li $t1,1 sw $t1,0($t0) li $v0,1 j fibDone L2: # Recursive Case: findFibonacci (theNumber - 1) sub $a0, $s0, 1 jal fib add $s1, $v0, $0 # Recursive Case: findFibonacci (theNumber - 2) sub $a0, $s0, 2 jal fib #calculate! add $t1, $s1, $v0 #save result in array sll $t0,$s0, 2 add $t0, $a1, $t0 sw $t1, 0( $t0 ) li $t2,3 div $t1,$t2 mfhi $t2 bne $t2,$zero, L3 add $a0,$t1,$0 li $v0,1 syscall la $a0,newLine li $v0,4 syscall L3: add $v0,$t1,$0 fibDone: lw $ra, 0($sp) lw $s0, 4( $sp) lw $s1, 8($sp) add $sp, $sp, 12 jr $ra ``` ### Insertion Sort ```cpp #include <stdlib.h> #include <stdio.h> void insertionSort(int array[], int length) { for (int i = 1; i < length; i++) { int current = array[i]; int j = i - 1; while (j >= 0 && array[j] > current) { array[j + 1] = array[j]; j--; } printf("%d\n", j + 1); array[j + 1] = current; } } int main() { int array[5]; for (int i = 0; i < 5; i++) { scanf("%d", &array[i]); } insertionSort(array, 5); for (int i = 0; i < 5; i++) { printf("%d\n", array[i]); } return 0; } ``` ![](https://i.imgur.com/AFuZhb8.png) #### 助教給的解答 ```assembly .data array: .space 20 .text .globl main main: la $s0, array li $s1, 0 #$t1 = i = 0 for1: slti $at,$s1,5 beq $at, $zero, exitFor1 sll $t2,$s1,2 # $t3 = i*4 add $t3, $s0,$t2 #input int li $v0, 5 syscall sw $v0,0($t3) addi $s1,$s1,1 j for1 exitFor1: add $a0, $s0, $0 addi $a1,$zero, 5 jal insertionSort li $s1, 0 #$s1 = i = 0 for2: slti $at,$s1,5 beq $at, $zero, exitFor2 sll $t1,$s1,2 # $t1 = i*4 add $t2, $s0,$t1 #$t2 = array[i] #print array[i] li $v0, 1 lw $a0,0($t2) syscall #change line addi $a0, $0, 0xA addi $v0, $0, 0xB syscall #i++ addi $s1,$s1,1 j for2 exitFor2: # Tell the system that the program is done. li $v0, 10 syscall insertionSort: subi $sp,$sp,12 sw $s0,0($sp) sw $s1,4($sp) sw $s2,8($sp) add $s0, $a0, $0 #$s0 = array[] li $s1,1 #$s1 = i = 1 forInSort: slt $at,$s1,$a1 beq $at, $zero, exitForInSort #int current = array[i]; sll $t0,$s1,2 #$t2 = i*4 add $t1,$s0,$t0 lw $s3,0($t1) # $s3 = current subi $s2,$s1,1 #$s2 = j = i - 1 whiileInForInSort: #j >= 0 && array[j] > current bltz $s2,exitWhileInForInSort sll $t0, $s2,2 add $t1,$s0,$t0 lw $t2,0($t1) # $t1 = array[j] slt $at,$s3,$t2 beq $at, $0, exitWhileInForInSort #array[j + 1] = array[j]; lw $t2,0($t1) sw $t2,4($t1) subi $s2,$s2,1 j whiileInForInSort exitWhileInForInSort: add $t0,$s2,1 #print index li $v0, 1 add $a0,$t0,$0 syscall #change line addi $a0, $0, 0xA addi $v0, $0, 0xB syscall sll $t0,$t0,2 add $t1,$s0,$t0 sw $s3,0($t1) addi $s1,$s1,1 j forInSort exitForInSort: lw $s0,0($sp) lw $s1,4($sp) lw $s2,8($sp) addi $sp,$sp,12 jr $ra ``` ### Transpose of a Matrix ```cpp #include <stdlib.h> #include <stdio.h> void inputMatrix(int A[3][3]) { for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { scanf("%d", &A[i][j]); } } } void transposeMatrixA1(int A[3][3], int T[3][3], int size) { for (int i = 0; i < size; i++) { for (int j = 0; j < size; j++) { T[j][i] = A[i][j]; } } } void transposeMatrixA2(int *B, int *T, int size) { int *ptrB, *ptrT, i; for (ptrB=B, ptrT=T, i = 1; ptrB<(B + (size*size)); ptrB++) { *ptrT = *ptrB; if (i < size) { ptrT += size; i++; } else { ptrT -= (size * (size - 1) - 1); i = 1; } } } void outputMatrix(int A[3][3]) { for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { printf("%d ", A[i][j]); } printf("\n"); } } int main() { int A[3][3]; int transposeOfA1[3][3]; int transposeOfA2[3][3]; int *ptrA = &A[0][0]; int *ptrTA2 = &transposeOfA2[0][0]; inputMatrix(A); transposeMatrixA1(A, transposeOfA1, 3); transposeMatrixA2(ptrA, ptrTA2, 3); outputMatrix(transposeOfA1); outputMatrix(transposeOfA2); return 0; } ``` ![](https://i.imgur.com/SALxU7h.png) #### 助教給的解答 ```assembly .data A: .space 36 transposeOfA1: .space 36 transposeOfA2: .space 36 .text .globl main main: la $s0,A #s0 = A[3][3] la $s1,transposeOfA1 #s1 = transposeOfA1[3][3] la $s2,transposeOfA2 #s2 = transposeOfA2[3][3] add $a0,$s0,$0 jal inputMatrix add $a0,$s0,$0 add $a1,$s1,$0 li $a2,3 jal transposeMatrixA1 add $a0,$s0,$0 add $a1,$s2,$0 li $a2,3 jal transposeMatrixA2 add $a1,$s1,$0 jal outputMatrix add $a1,$s2,$0 jal outputMatrix # Tell the system that the program is done. li $v0, 10 syscall inputMatrix: # addr = baseAddr + (rowIndex * colSize + colIndex)*datasize add $t0,$zero,$0 #i=0 for1InputMatrix: slti $at,$t0,3 beq $at, $zero,exitfor1InputMatrix add $t1,$zero,$0 #j=0 for2InputMatrix: slti $at,$t1,3 beq $at,$zero,exitfor2InputMatrix mul $t4,$t0,3 add $t4,$t4,$t1 mul $t4,$t4,4 add $t4,$t4,$a0 li $v0,5 syscall sw $v0,0($t4) addi $t1,$t1,1 j for2InputMatrix exitfor2InputMatrix: addi $t0,$t0,1 j for1InputMatrix exitfor1InputMatrix: jr $ra transposeMatrixA2: add $t0,$a0,$0 #ptrB = B add $t1,$a1,$0 #ptrT = T li $t2,1 # i =1 forTransposeMatrixA2: mul $t3,$a2,$a2 sll $t3,$t3,2 #t3*=4 add $t3,$t3,$a0 #t3 = (B + (size * size) slt $at,$t0,$t3 beq $at, $zero,exitForTransposeMatrixA2 #*ptrT = *ptrB lw $t3,0($t0) sw $t3,0($t1) slt $at,$t2,$a2 beq $at,$zero,L1 sll $t3,$a2,2 add $t1,$t1,$t3 #ptrT += size addi $t2,$t2,1 #i++ j L2 L1: subi $t3,$a2,1 mul $t3,$t3,$a2 subi $t3,$t3,1 #$t3 = (size * (size - 1) - 1) sll $t3,$t3,2 #$t3 *= 4 sub $t1,$t1,$t3 #prtT -= (size * (size - 1) - 1) li $t2,1 #i = 1 L2: addi $t0,$t0,4 #ptrB++ j forTransposeMatrixA2 exitForTransposeMatrixA2: jr $ra transposeMatrixA1: add $t0,$zero,$0 # i = 0 for1TransposeMatrixA1: slt $at,$t0,$a2 beq $at,$zero,exitfor1TransposeMatrixA1 add $t1,$zero, $0 # j = 0 for2TransposeMatrixA1: slt $at,$t1,$a2 beq $at,$zero,exitfor2TransposeMatrixA1 mul $t3,$t0,$a2 add $t3,$t3,$t1 mul $t3,$t3,4 add $t3,$t3,$a0 #t3 = A[i][j] address mul $t4,$t1,$a2 add $t4,$t4,$t0 mul $t4,$t4,4 add $t4,$t4,$a1 #t4 = T[i][j] address lw $t5,0($t3) sw $t5,0($t4) addi $t1,$t1,1 j for2TransposeMatrixA1 exitfor2TransposeMatrixA1: addi $t0,$t0,1 j for1TransposeMatrixA1 exitfor1TransposeMatrixA1: jr $ra outputMatrix: add $t0,$zero,$0 for1OutputMatrix: slti $at,$t0,3 beq $at,$zero,exitFor1OutputMatrix add $t1,$zero,$0 for2OutputMatrix: slti $at,$t1,3 beq $at,$zero,exitFor2OutputMatrix mul $t3,$t0,3 add $t3,$t3,$t1 mul $t3,$t3,4 add $t3,$t3,$a1 #t3 = A[i][j] address lw $a0,0($t3) li $v0,1 syscall # print space, 32 is ASCII code for space li $a0, 32 li $v0, 11 # syscall number for printing character syscall addi $t1,$t1,1 j for2OutputMatrix exitFor2OutputMatrix: addi $a0, $0, 0xA addi $v0, $0, 0xB syscall addi $t0,$t0,1 j for1OutputMatrix exitFor1OutputMatrix: jr $ra ```