hackmd-github-sync-badge

MIPS Note

tags: School


MIPS指令集

Compare

  • j: jump,跳轉到指定位址。
    jr: jump register,跳轉到暫存器存放的位址。
    jal: jump and link,跳轉到指定位址並保存返回位址
  • lw: load word,memory->register
    sw: store word,register->memory

常用暫存器

名稱 編號 用途
$s0 ~ $s7 16 ~ 23 保留暫存器
$t0 ~ $t7 8 ~ 15 臨時暫存器
$v0 ~ $v1 2 ~ 3 傳回值暫存器
$a0 ~ $a3 4 ~ 7 參數暫存器
$sp 29 堆疊指標
$ra 31 程式返回位置

caller & callee


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.
    ​​​​.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

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
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

int fact(int n) {
    if (n < 1) {
        return f;
    } else {
        return n * fact(n - 1);
    }
}
  • argument n in $a0
  • result in $v0

3. array

4. while loop

while (save[i] == k) {
    i += 1;
}
  • i in $s3, k in $s5, addr. of save in $s6
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 填空格

完全不一樣版(chatGPT)

.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),它通常會被放置在程式碼中的某個位置,例如:
      ​​​​​​​​loop:
      ​​​​​​​​    # 處理循環中的程式碼
      ​​​​​​​​    j loop # 無條件跳轉回 loop 標籤處繼續執行
      
    • 在上面的例子中,loop 是一個標籤,它標記了程式碼中一個循環的開始位置。當程式碼執行到 j loop 時,將會無條件跳轉到 loop 標籤處繼續執行循環中的程式碼。

填空格版

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

#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
59
180
58
180
90
-1
18
underweight
overweight
180
80
180
81
180
50
-1
24
overweight
underweight
178
80
150
50
196
76
190
44
-1
overweight
22
19
underweight

助教給的解答

.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

自己寫的

.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

#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
3
2
3
5
8
21
21
2 1
13 1
3
2
3
5
8
21
13
21
34
55
144
89
233

助教給的解答

.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

#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;
}

助教給的解答

.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

#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;
}

助教給的解答

.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