×
Samples Blogs Make Payment About Us Reviews 4.9/5 Order Now

Transform Matrix In MIPS Assembly Language Assignment Solution

July 09, 2024
Rehana Magnus
Rehana Magnus
🇨🇦 Canada
Assembly Language
Rehana Magnus, PhD in Computer Science from the esteemed Acadia Institute of Technology, Canada. With 6 years of experience, specializes in assembly language programming. Proficient in low-level coding, optimizing performance, and enhancing system functionality.
Key Topics
  • Instructions
  • Requirements and Specifications
Tip of the day
Familiarize yourself with OCaml's pattern matching; it simplifies handling recursive data structures like lists and trees, making your code concise and easier to debug.
News
In 2024, Girls Who Code introduced a Data Science + AI track in their free summer programs for high school students, fostering skills in cybersecurity and creative coding​

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

Related Samples

Discover our curated collection of free Assembly Language assignment samples. These resources offer practical examples and solutions to enhance your understanding of low-level programming concepts. Explore real-world applications and coding techniques to excel in your Assembly Language projects.