+1 (315) 557-6473 

Transform Matrix In MIPS Assembly Language Assignment Solution.


Instructions

Objective
Write a MIPS assignment program in assembly language to transform matrices.

Requirements and Specifications

### Part 1 -- Initialize Data Structure
**int initialize(char\* filename, Buffer\* buffer)**
This function takes two arguments -- a string *filename* and the address of a data structure *buffer* (as defined above). The function will read the content in *filename*, parse it and store the contents in *buffer*. The contents in *buffer* should be in the format defined for the data structure above. So, the first two elements should be the no. of rows and columns of a matrix and the remaining elements should be the integers of the matrix. One way to do this is to read the file one character at a time, and store them in the buffer as integers in appropriate positions.
If the file is read without any errors and the buffer is initialized properly, then the function should return 1 in *$v0*.
The function should return -1 in *$v0* if an error occurs during initialization. When this happens the *buffer* data structure should remain unchanged. You should assume the buffer contains all zeros before initialization. Initialization errors can occur due to the following reasons:
  • File I/O error.
  • The first two lines are not [1-10].
  • The file has more than X lines (excluding the first two lines), where X is the no. of rows in the first line.
  • The file has more than Y columns (excluding the first two lines), where Y is the no. of columns in the second line.
  • Lines 3 and after have non-numeric characters.
  • Numbers in lines 3 and after (except the last number) do not end with exactly one whitespace.
**Note that this function must handle newline characters in both Windows and UNIX-based systems**. On Windows, line endings are terminated with a combination of carriage return (*\r*) and newline (*\n*) characters, also referred to as CR/LF. On UNIX-based systems, line endings are just the newline character (*\n*).
### Part 2 -- Write Buffer To File
**void write_file(char\* filename, Buffer\* buffer)**
This function takes two arguments -- a string filename and the address of the buffer data structure (as defined above). It should write the data in *buffer* to the file in *filename*. The format of the file is the same as defined previously.
### Part 3 -- Rotate Clockwise By 90
**void rotate_clkws_90(Buffer\* buffer, char\* filename)**
This function takes two arguments -- the address of the *buffer* data structure and a string *filename*. It rotates the matrix in *buffer* clockwise by 90 degrees and writes it to *filename*.
### Part 4 -- Rotate Clockwise By 180
**void rotate_clkws_180(Buffer\* buffer, char\* filename)**
This function takes two arguments -- the address of the *buffer* data structure and a string *filename*. It rotates the matrix in *buffer* clockwise by 180 degrees and writes it to *filename*.
### Part 5 -- Rotate Clockwise By 270
**void rotate_clkws_270(Buffer\* buffer, char\* filename)**
This function takes two arguments -- the address of the *buffer* data structure and a string *filename*. It rotates the matrix in *buffer* clockwise by 270 degrees and writes it to *filename*.
### Part 6 -- Mirroring
**void mirror(Buffer\* buffer, char\* filename)**
This function takes two arguments -- the address of the *buffer* data structure and a string *filename*. It creates a mirror of the matrix in *buffer* writes it to *filename*. For example, consider the following matrix with 2 rows and 3 columns:
### Part 7 -- Duplicates
**(int, int) duplicate(Buffer\* buffer)**
This function takes the data structure *buffer* as an argument. Assume that the matrix in *buffer* contains only binary values 0 and 1. The function checks to see if the matrix has any duplicate rows. If a duplicate row exists in the matrix then the function returns 1 in *$v0* and the index (starting at 1) of the first duplicate row in *$v1*. If the matrix has no duplicate rows then the function returns -1 in *$v0* and 0 in *$v1*
Assume that buffer points to a valid Buffer struct. You do not need to validate the buffer.
Screenshots of output
Program to transform matrix in Mips assembly
Program to transform matrix in Mips assembly 1
Program to transform matrix in Mips assembly 2
Program to transform matrix in Mips assembly 3
Source Code
######### FULL NAME ##########
######### SBU ID ##########
######### NET ID ##########
######## DO NOT ADD A DATA SECTION ##########
######## DO NOT ADD A DATA SECTION ##########
######## DO NOT ADD A DATA SECTION ##########
.text
read_char:
    addi $sp, $sp, -1 # allocate space in stack to read a char
    li $v0, 14 # syscall to read a file
    move $a1, $sp # read in stack
    li $a2, 1 # read 1 char
    syscall # read file
    blt $v0, $0, rc_exit # if < 0, it's an error
    beq $v0, $0, rc_exit # if = 0, return
    lb $v0, 0($sp) # load read char
rc_exit:
    addi $sp, $sp, 1 # restore stack
    jr $ra # return
# read an integer from the file
# Receives: $a0 = file descriptor
# Returns: $v0 = integer, $v1 = next char if no errors, < 0 if error
read_integer:
 addi $sp, $sp, -16 # allocate space on stack
 sw $ra, 0($sp) # save registers on stack
 sw $s0, 4($sp)
 sw $s1, 8($sp)
 sw $s2,12($sp)
    move $s2, $a0 # save file descriptor
    li $s1, 0 # number of digits
    li $s0, 0 # start number in zero
ri_loop:
    move $a0, $s2 # pass file descriptor
    jal read_char # read a char
    blt $v0, $0, ri_exit # if < 0, it's an error
    beq $v0, $0, ri_exit # if = 0, return
    li $t0, 48 # load ascii code for '0'
    blt $v0, $t0, ri_exit # if not a digit, end
    li $t0, 57 # load ascii code for '9'
    bgt $v0, $t0, ri_exit # if not a digit, end
    addi $v0, $v0, -48 # convert ascii to decimal digit
    li $t0, 10
    mul $s0, $s0, $t0 # multiply old number by 10
    add $s0, $s0, $v0 # add digit
    addi $s1, $s1, 1 # increment number of digits
    j ri_loop # repeat loop
ri_exit:
    bne $s1, $0, ri_ok # if at least a digit was read, it's ok
    li $v0, -1 # else, it's an error
ri_ok:
    move $v1, $v0 # set code to last char or error
    move $v0, $s0 # return number
 lw $s2,12($sp)
 lw $s1, 8($sp)
 lw $s0, 4($sp)
 lw $ra, 0($sp)
 addi $sp, $sp, 16 # restore stack
    jr $ra
write_char:
    addi $sp, $sp, -1 # allocate space in stack to write a char
    sb $a1, 0($sp) # save char to write in stack
    li $v0, 15 # syscall to write a file
    move $a1, $sp # write from stack
    li $a2, 1 # write 1 char
    syscall # write file
    addi $sp, $sp, 1 # restore stack
    jr $ra # return
# write an integer to a file
# Receives: $a0 = file descriptor, $a1 = integer to write
# Returns: $v0 < 0 if error, number of chars written if success
write_integer:
 addi $sp, $sp, -12 # allocate space on stack
 sw $ra, 0($sp) # save registers on stack
 sw $s0, 4($sp)
 sw $s1, 8($sp)  
    # convert number to a string of chars
    li $t0, 0 # insert a marker in the stack
    addi $sp, $sp, -1 # push value to stack
    sb $t0, 0($sp)
    li $t1, 10 # load 10 for divisions
wi_conv_num:
    div $a1, $t1 # divide number by 10
    mflo $a1 # save quotient in a1
    mfhi $t0 # load remainder in t0 [0-9]
    addi $t0, $t0, 48 # convert digit to ascii
    addi $sp, $sp, -1 # push digit to stack
    sb $t0, 0($sp)
    bne $a1, $0, wi_conv_num # repeat until number is zero
    # save converted number in file
    move $s0, $a0 # save file descriptor
    li $s1, 0 # number of written chars is zero
wi_loop:
    lb $a1, 0($sp) # load char to write
    addi $sp, $sp, 1 # pop from stack
    beq $a1, $0, wi_exit # if end of number, return
    move $a0, $s0 # pass file descriptor
    jal write_char # write a char
    blt $v0, $0, wi_error # if < 0, it's an error
    add $s1, $s1, $v0 # increment number of written chars
    j wi_loop # repeat loop
wi_error:
    li $s1, -1 # return error
wi_exit:
    move $v0, $s1 # return number of chars written
 lw $s1, 8($sp)
 lw $s0, 4($sp)
 lw $ra, 0($sp)
 addi $sp, $sp, 12 # restore stack
    jr $ra
.globl initialize
initialize:
 addi $sp, $sp, -24 # allocate space on stack
 sw $ra, 0($sp) # save registers on stack
 sw $s0, 4($sp)
 sw $s1, 8($sp)
 sw $s2, 12($sp)
 sw $s3, 16($sp)
 sw $s4, 20($sp)
    move $s0, $a1 # save buffer pointer in s0
    li $v0, 13 # syscall to open a file
    li $a1, 0 # open for reading
    li $a2, 0 # mode = 0
    syscall # open file
    move $s1, $v0 # save file descriptor
    blt $v0, $0, init_error # if < 0, there was an error
    # read rows
    move $a0, $s1 # pass file descriptor
    jal read_integer # read integer
    blt $v1, $0, init_error # if < 0, there was an error
    move $s2, $v0 # save rows
    blt $s2, 1, init_error # if rows < 1, it's an error
    bgt $s2, 10, init_error # if rows > 10, it's an error
    sw $s2, 0($s0) # save in buffer
    beq $v1, 10, init_rd_cols # if ending char was a \n, read cols
    bne $v1, 13, init_error # if not a \r, it's an error
    # if \r, read the \n
    move $a0, $s1 # pass file descriptor
    jal read_char # read char
    blt $v0, $0, init_error # if < 0, there was an error
    bne $v0, 10, init_error # if not a \n, it's an error
init_rd_cols:
    # read cols
    move $a0, $s1 # pass file descriptor
    jal read_integer # read integer
    blt $v1, $0, init_error # if < 0, there was an error
    move $s3, $v0 # save cols
    blt $s3, 1, init_error # if cols < 1, it's an error
    bgt $s3, 10, init_error # if cols > 10, it's an error
    sw $s3, 4($s0) # save in buffer
    beq $v1, 10, init_rd_mat # if ending char was a \n, read matrix
    bne $v1, 13, init_error # if not a \r, it's an error
    # if \r, read the \n
    move $a0, $s1 # pass file descriptor
    jal read_char # read char
    blt $v0, $0, init_error # if < 0, there was an error
    bne $v0, 10, init_error # if not a \n, it's an error
init_rd_mat:
    add $s0, $s0, 8 # advance pointer to start of matrix
init_rows:
    move $s4, $s3 # load number of columns
init_cols:
    # read matrix number
    move $a0, $s1 # pass file descriptor
    jal read_integer # read integer
    blt $v1, $0, init_error # if < 0, there was an error
    sw $v0, 0($s0) # save in buffer
    add $s0, $s0, 4 # advance pointer to next position in matrix
    beq $s4, 1, init_nxt_col # if last val, skip test
    bne $v1, 32, init_error # if not a space after number, it's an error
init_nxt_col:
    addi $s4, $s4, -1 # decrement remaining cols
    bne $s4, $0, init_cols # if not zero, repeat
    beq $v1, 10, init_nxt_row # if \n space after number, read next row
    bne $v1, 13, init_error # if not a \r, it's an error
    # if \r, read the \n
    move $a0, $s1 # pass file descriptor
    jal read_char # read char
    blt $v0, $0, init_error # if < 0, there was an error
    bne $v0, 10, init_error # if not a \n, it's an error
init_nxt_row:
    addi $s2, $s2, -1 # decrement remaining rows
    bne $s2, $0, init_rows # if not zero, repeat
    # read end of file
    move $a0, $s1 # pass file descriptor
    jal read_char # read char
    blt $v0, $0, init_error # if < 0, there was an error
    bne $v0, $0, init_error # if not end of file, it's an error
    li $v0, 16 # system call for close file
    move $a0, $s1 # file descriptor to close
    syscall # close file
    li $v0, 1 # return without error
    j init_exit
init_error:
    li $v0, -1 # return error code
init_exit:
 lw $s4, 20($sp) # load register values from stack
 lw $s3, 16($sp)
 lw $s2, 12($sp)
 lw $s1, 8($sp)
 lw $s0, 4($sp)
 lw $ra, 0($sp)
 addi $sp, $sp, 24 # restore stack
    jr $ra
.globl write_file
write_file:
 addi $sp, $sp, -28 # allocate space on stack
 sw $ra, 0($sp) # save registers on stack
 sw $s0, 4($sp)
 sw $s1, 8($sp)
 sw $s2, 12($sp)
 sw $s3, 16($sp)
 sw $s4, 20($sp)
 sw $s5, 24($sp)
    move $s0, $a1 # save buffer pointer in s0
    li $v0, 13 # syscall to open a file
    li $a1, 1 # open for writing
    li $a2, 0 # mode = 0
    syscall # open file
    move $s1, $v0 # save file descriptor
    blt $v0, $0, wf_error # if < 0, there was an error
    li $s2, 0 # number of written chars = 0
    # write rows
    move $a0, $s1 # pass file descriptor
    lw $a1, 0($s0) # load rows from buffer
    jal write_integer # write integer
    blt $v0, $0, wf_error # if < 0, there was an error
    add $s2, $s2, $v0 # add written chars
    # write a newline
    move $a0, $s1 # pass file descriptor
    li $a1, 13 # cr char
    jal write_char # write char
    blt $v0, $0, wf_error # if < 0, there was an error
    add $s2, $s2, $v0 # add written chars
    move $a0, $s1 # pass file descriptor
    li $a1, 10 # newline char
    jal write_char # write char
    blt $v0, $0, wf_error # if < 0, there was an error
    add $s2, $s2, $v0 # add written chars
    # write cols
    move $a0, $s1 # pass file descriptor
    lw $a1, 4($s0) # load cols from buffer
    jal write_integer # write integer
    blt $v0, $0, wf_error # if < 0, there was an error
    add $s2, $s2, $v0 # add written chars
    # write a newline
    move $a0, $s1 # pass file descriptor
    li $a1, 13 # cr char
    jal write_char # write char
    blt $v0, $0, wf_error # if < 0, there was an error
    add $s2, $s2, $v0 # add written chars
    move $a0, $s1 # pass file descriptor
    li $a1, 10 # newline char
    jal write_char # write char
    blt $v0, $0, wf_error # if < 0, there was an error
    add $s2, $s2, $v0 # add written chars
    lw $s3, 0($s0) # load rows
    lw $s4, 4($s0) # load cols
    add $s0, $s0, 8 # advance pointer to start of matrix
wf_rows:
    move $s5, $s4 # load number of columns
wf_cols:
    # write matrix number
    move $a0, $s1 # pass file descriptor
    lw $a1, 0($s0) # load value from buffer
    add $s0, $s0, 4 # advance pointer to next position in matrix
    jal write_integer # write integer
    blt $v0, $0, wf_error # if < 0, there was an error
    add $s2, $s2, $v0 # add written chars
    beq $s5, 1, wf_nxt_col # if last val, skip space write
    # write a space
    move $a0, $s1 # pass file descriptor
    li $a1, 32 # space char
    jal write_char # write char
    blt $v0, $0, wf_error # if < 0, there was an error
    add $s2, $s2, $v0 # add written chars
wf_nxt_col:
    addi $s5, $s5, -1 # decrement remaining cols
    bne $s5, $0, wf_cols # if not zero, repeat
    # write a newline
    move $a0, $s1 # pass file descriptor
    li $a1, 13 # newline char
    jal write_char # write char
    blt $v0, $0, wf_error # if < 0, there was an error
    add $s2, $s2, $v0 # add written chars
    move $a0, $s1 # pass file descriptor
    li $a1, 10 # newline char
    jal write_char # write char
    blt $v0, $0, wf_error # if < 0, there was an error
    add $s2, $s2, $v0 # add written chars
    addi $s3, $s3, -1 # decrement remaining rows
    bne $s3, $0, wf_rows # if not zero, repeat
    li $v0, 16 # system call for close file
    move $a0, $s1 # file descriptor to close
    syscall # close file
    move $v0, $s2 # return number of chars written
    j wf_exit
wf_error:
    li $v0, -1 # return error code
wf_exit:
 lw $s5, 24($sp) # load register values from stack
 lw $s4, 20($sp)
 lw $s3, 16($sp)
 lw $s2, 12($sp)
 lw $s1, 8($sp)
 lw $s0, 4($sp)
 lw $ra, 0($sp)
 addi $sp, $sp, 28 # restore stack
    jr $ra
.globl rotate_clkws_90
rotate_clkws_90:
 addi $sp, $sp, -4 # allocate space on stack
 sw $ra, 0($sp) # save registers on stack
    move $fp, $sp # point to current sp
    lw $t0, 0($a0) # load rows
    lw $t1, 4($a0) # load cols
    mul $t2, $t0, $t1 # rows*cols
    sll $t2, $t2, 2 # rows*cols*4
    add $t2, $t2, 8 # add 2 words (rows, cols)
    sub $sp, $sp, $t2 # allocate space in stack to save a new buffer
    move $t2, $sp # point to buffer
    sw $t1, 0($t2) # save cols as rows for rotated matrix
    sw $t0, 4($t2) # save rows as cols for rotated matrix
    sll $t3, $t0, 2 # rows*4 = line size for rotated matrix
    # rotation
    move $t4, $a0 # point to initial buffer
    move $t7, $t0 # load rows
r90_rows:
    move $t8, $t1 # load cols
    addi $t5, $t7, -1 # (rows -1)
    sll $t5, $t5, 2 # current (rows -1) * 4
    add $t5, $t5, $t2 # address of mat[rows-1]
r90_cols:
    lw $t6, 8($t4) # load value from initial buffer
    sw $t6, 8($t5) # save value in end buffer
    addi $t4, $t4, 4 # advance to next position
    add $t5, $t5, $t3 # advance to next position
    addi $t8, $t8, -1 # decrement remaining columns
    bne $t8, $0, r90_cols # repeat loop while not zero
    addi $t7, $t7, -1 # decrement remaining rows
    bne $t7, $0, r90_rows # repeat loop while not zero
    # write matrix
    move $a0, $a1 # pass filename
    move $a1, $sp # pass buffer in stack
    jal write_file # write the file
    move $sp, $fp # restore stack pointer
    lw $ra, 0($sp)
    addi $sp, $sp, 4 # restore stack
    jr $ra
.globl rotate_clkws_180
rotate_clkws_180:
 addi $sp, $sp, -4 # allocate space on stack
 sw $ra, 0($sp) # save registers on stack
    move $fp, $sp # point to current sp
    lw $t0, 0($a0) # load rows
    lw $t1, 4($a0) # load cols
    mul $t2, $t0, $t1 # rows*cols
    sll $t2, $t2, 2 # rows*cols*4
    add $t2, $t2, 8 # add 2 words (rows, cols)
    sub $sp, $sp, $t2 # allocate space in stack to save a new buffer
    move $t2, $sp # point to buffer
    sw $t0, 0($t2) # save rows for rotated matrix
    sw $t1, 4($t2) # save cols for rotated matrix
    addi $t3, $t0, -1 # (rows -1)
    mul $t3, $t3, $t1 # (rows -1) * cols
    addi $t5, $t1, -1 # (cols -1)
    add $t5, $t5, $t3 #current (rows -1) * cols + (cols -1)
    sll $t5, $t5, 2 # ((rows -1) * cols + (cols -1)) * 4
    add $t5, $t5, $t2 # address of mat[rows-1][cols-1]
    # rotation
    move $t4, $a0 # point to initial buffer
    move $t7, $t0 # load rows
r180_rows:
    move $t8, $t1 # load cols
r180_cols:
    lw $t6, 8($t4) # load value from initial buffer
    sw $t6, 8($t5) # save value in end buffer
    addi $t4, $t4, 4 # advance to next position
    addi $t5, $t5, -4 # advance to next position
    addi $t8, $t8, -1 # decrement remaining columns
    bne $t8, $0, r180_cols # repeat loop while not zero
    addi $t7, $t7, -1 # decrement remaining rows
    bne $t7, $0, r180_rows # repeat loop while not zero
    # write matrix
    move $a0, $a1 # pass filename
    move $a1, $sp # pass buffer in stack
    jal write_file # write the file
    move $sp, $fp # restore stack pointer
    lw $ra, 0($sp)
    addi $sp, $sp, 4 # restore stack
    jr $ra
.globl rotate_clkws_270
rotate_clkws_270:
 addi $sp, $sp, -4 # allocate space on stack
 sw $ra, 0($sp) # save registers on stack
    move $fp, $sp # point to current sp
    lw $t0, 0($a0) # load rows
    lw $t1, 4($a0) # load cols
    mul $t2, $t0, $t1 # rows*cols
    sll $t2, $t2, 2 # rows*cols*4
    add $t2, $t2, 8 # add 2 words (rows, cols)
    sub $sp, $sp, $t2 # allocate space in stack to save a new buffer
    sw $t1, 0($sp) # save cols as rows for rotated matrix
    sw $t0, 4($sp) # save rows as cols for rotated matrix
    addi $t2, $t1, -1 # (cols -1)
    mul $t2, $t2, $t0 # current (cols -1) * rows
    sll $t2, $t2, 2 # current (cols -1) * rows * 4
    add $t2, $t2, $sp # address of mat[cols-1][0]
    sll $t3, $t0, 2 # rows*4 = line size for rotated matrix
    # rotation
    move $t4, $a0 # point to initial buffer
    move $t7, $t0 # load rows
r270_rows:
    move $t8, $t1 # load cols
    move $t5, $t2 # load current mat[cols -1][row] position
r270_cols:
    lw $t6, 8($t4) # load value from initial buffer
    sw $t6, 8($t5) # save value in end buffer
    addi $t4, $t4, 4 # advance to next position
    sub $t5, $t5, $t3 # advance to next position
    addi $t8, $t8, -1 # decrement remaining columns
    bne $t8, $0, r270_cols # repeat loop while not zero
    addi $t2, $t2, 4 # advance to next col in rotated matrix
    addi $t7, $t7, -1 # decrement row
    bne $t7, $0, r270_rows # repeat loop while not zero
    # write matrix
    move $a0, $a1 # pass filename
    move $a1, $sp # pass buffer in stack
    jal write_file # write the file
    move $sp, $fp # restore stack pointer
    lw $ra, 0($sp)
    addi $sp, $sp, 4 # restore stack
    jr $ra
.globl mirror
mirror:
 addi $sp, $sp, -4 # allocate space on stack
 sw $ra, 0($sp) # save registers on stack
    move $fp, $sp # point to current sp
    lw $t0, 0($a0) # load rows
    lw $t1, 4($a0) # load cols
    mul $t2, $t0, $t1 # rows*cols
    sll $t2, $t2, 2 # rows*cols*4
    add $t2, $t2, 8 # add 2 words (rows, cols)
    sub $sp, $sp, $t2 # allocate space in stack to save a new buffer
    sw $t0, 0($sp) # save rows for rotated matrix
    sw $t1, 4($sp) # save cols for rotated matrix
    addi $t2, $t1, -1 # (cols -1)
    sll $t2, $t2, 2 # (cols -1) * 4
    add $t2, $t2, $sp # address of mat[0][cols-1]
    sll $t3, $t1, 2 # cols * 4 = linesize
    # mirroring
    move $t4, $a0 # point to initial buffer
    move $t7, $t0 # load rows
mirror_rows:
    move $t8, $t1 # load cols
    move $t5, $t2 # load current mat[row][cols -1] position
mirror_cols:
    lw $t6, 8($t4) # load value from initial buffer
    sw $t6, 8($t5) # save value in end buffer
    addi $t4, $t4, 4 # advance to next position
    addi $t5, $t5, -4 # advance to next position
    addi $t8, $t8, -1 # decrement remaining columns
    bne $t8, $0, mirror_cols # repeat loop while not zero
    add $t2, $t2, $t3 # advance to next col in mirrored matrix
    addi $t7, $t7, -1 # decrement row
    bne $t7, $0, mirror_rows # repeat loop while not zero
    # write matrix
    move $a0, $a1 # pass filename
    move $a1, $sp # pass buffer in stack
    jal write_file # write the file
    move $sp, $fp # restore stack pointer
    lw $ra, 0($sp)
    addi $sp, $sp, 4 # restore stack
    jr $ra
.globl duplicate
duplicate:
 addi $sp, $sp, -8 # allocate space on stack
 sw $s0, 0($sp) # save registers on stack
 sw $s1, 4($sp)
    lw $t0, 0($a0) # load rows
    lw $t1, 4($a0) # load cols
    addi $t0, $t0, -1 # rows - 1
    sll $t2, $t1, 2 # cols *4 = line size
    move $t3, $a0 # point to initial buffer
    li $t4, 0 # current rows
dup_findrow:
    addi $t6, $t4, 1 # initial rows = curr row + 1
    add $t5, $t3, $t2 # point to next row
    j dup_cmp # jump to comparison
dup_rows:
    move $t7, $t1 # load cols
    move $s0, $t3 # save current row
    move $s1, $t5 # save current row
dup_cols:
    lw $t8, 8($t3) # load value from initial row
    lw $t9, 8($t5) # load value from curr row
    bne $t8, $t9, no_dup # if not equal, is not a duplicate
    addi $t3, $t3, 4 # advance to next position
    addi $t5, $t5, 4 # advance to next position
    addi $t7, $t7, -1 # decrement remaining columns
    bne $t7, $0, dup_cols # repeat loop while not zero
    # it will end here if duplicate
    li $v0, 1 # duplicate found
    add $v1, $t6, 1 # return row index
    j dup_exit
no_dup:
    addi $t6, $t6, 1 # increment row
    move $t3, $s0 # restart initial row
    add $t5, $s1, $t2 # advance to next row
dup_cmp:
    ble $t6, $t0, dup_rows # repeat loop while <= rows-1
    add $t3, $t3, $t2 # advance to next row
    addi $t4, $t4, 1 # increment row
    blt $t4, $t0, dup_findrow # repeat loop while < rows-1
    # it will end here if no duplicate
    li $v0, -1 # no duplicate found
    li $v1, 0 # return 0
dup_exit:
    lw $s0, 0($sp)
    lw $s1, 4($sp)
    addi $sp, $sp, 8 # restore stack
    jr $ra