Reformat text in MIPS assembly

Assignment

Solution 

program.asm 

.data

fnf:  .ascii  “The file was not found: ”

###important: UPDATE THIS PATH TO WHERE YOU SAVED THE TEXT FILE

#asciiz directive creates null-terminated string

file: .asciiz     “C:/Users/Rami/Documents/2017/mp1/input.txt”

pstring:.asciiz   ” printable characters.\nFile Contents: \n”

buffer: .space 1024

cstring:.asciiz   “\nFile Contents after capitalization: \n”

.text

#QUICK REFERENCE OF REGISTER MAPPINGS

#$s0 – save the file descriptor of the file containing text

#$s1 – save the address of the buffer text was loaded (base address)

#$s2 – iterator (i) to buffer character array

#$s3 – count number of printable characters

#$t0 – where we will temporarily keep the address of CURRENT character, i.e. $s1 + $s2

#$t1 – where we will temporarity load the current character, i.e. character at address in $t0

#These lines opens and reads the file containing text to be modified

main:

li    $v0, 13                 # Set $v0 to 13 for syscall to open file

la    $a0, file         # Load file to read, $a0 set to address of string

# containing filename

li    $a1, 0                  # Set read-only flag

li    $a2, 0                  # Set mode

syscall                       # the file descriptor will be returned in $v0

blt   $v0, 0, err       # Go to handler if failed to open file

# blt is a pseudo-instruction

# but you can use those in this assignment

add   $s0, $v0, $zero   # Save file descriptor in $v0 to new register $s0

# because $v0 will be used in other system calls

# These files read text from the file we just loaded

read:

li    $v0, 14                 # Set $v0 to 14 for system call to read file

add   $a0, $s0, $zero   # Load file descriptor to $a0, we previously saved in $s0

la    $a1, buffer       # Set $a1 to address of input buffer where

# text will be loaded to

li    $a2, 1024         # Set $a2 to number of characters to read

syscall                       # $v0 will contain number of characters (bytes) read

# $v0 set to -1 if error

add $s1,$a1,$zero # save address of buffer to $s1

#set last byte to null so we know when to stop loop later

add   $t4, $s1, $v0     #recall, $v0 has the number of characters, so

#this will give us the address of the byte

#just after the last character

sb    $zero, 0($t4)     #ASCII code for NULL is ‘0’

#initialize some registers

init:

li    $s2, 0                  # $s2 will be message character iterator i

# initialize i=0

li  $s3, 0              # $s3 will count the number of printable characters

#loop to count PRINTABLE characters

loop:

add   $t0, $s1, $s2           # $t0 <= BA + i, address of current character

# BA: address start of buffer, in $s1

lb    $t1, 0($t0)             # load char in buffer[i] to $t1

beq   $t1, $zero, print   # null, reached end of buffer

#let’s check for printable characters

#see ASCII table; let’s not count any ASCII code less than 33 (exclamation point)

#or greater 126 (~)

#note that you can use the pseudo-instruction blt and bge as well

#even though they are not native MIPS instructions, qtSPIM will handle them

slti $t2,$t1,33         #$t2 is 1 if $t1<33; 0 if >=33

#i.e. if $t2 is 1, not printable character

bne $t2,$zero,next      #move to next character if $t2 is 1

slti $t3,$t1,127  #note: will only come here if $t1>=33 ($t2 is 0)

#$t3 is 1 if $t1<127; 0 if $t1>=127

#therefore, this is a printable character if

#$t2 is 0 AND $t3 is 1

beq $t3,$zero,next      #move to next character if $t3 is 0 ($t1>=127)

addi $s3,$s3,1          #note: will only come here if ASCII code is

#between 33 and 126 (what we consider as printable characters)

next:                         #move to next character/iteration

addi $s2, $s2, 1  #i++

j     loop              #continue iterating through each character

# Print data to console

print:

li    $v0, 1                  # System call to print integer

add   $a0, $s3, $zero   # Load to $a0 integer to print

syscall

#print pstring

li    $v0, 4                  # System call to print string

la    $a0, pstring      # Load to $a0 string to print

syscall

#print actual file contents

li    $v0, 4                  # System call to print string

add   $a0, $s1, $zero   # copy BA of buffer to $a0

syscall

# Close File

close:

li    $v0, 16                 # Set $v0 to 16 for system call to close file

add   $a0, $s0, $zero   # Load File Descriptor

syscall

#correct case

jalcorrect_case    # call the procedure to correct the case

#print cstring

li    $v0, 4                  # System call to print string

la    $a0, cstring      # Load to $a0 string to print

syscall

#print corrected file contents

li    $v0, 4                  # System call to print string

add   $a0, $s1, $zero   # copy BA of buffer to $a0

syscall

j     done        # Goto done

#Error

err:

li    $v0, 4            # System call to print string

la    $a0, fnf    # Load Error String

syscall

# Done

done:

li    $v0, 10           # Exit Syscall

syscall

# Procedure that corrects the case of the characters in the text buffer

# On entry:

#   $s1 = pointer to null-terminated text buffer

correct_case:

add $t0,$s1,$zero       # we will use t0 to point to the current char in the buffer

li  $t3,1               # we will use t3 as the flag for capitalizing characters, first char is uppercase

cloop:                      # go through each character and correct capitalization

lb    $t1, 0($t0)             # load char in buffer[i] to $t1

beq   $t1, $zero, return  # null, reached end of buffer

li  $t2, 10             # newline char

beq $t1, $t2, setcap    # if is’t a newline, set capitalization

li  $t2, 33             # exclamation

beq $t1, $t2, setcap    # if is’t an exclamation, set capitalization

li  $t2, 46             # period

beq $t1, $t2, setcap    # if is’t a period, set capitalization

li  $t2, 63             # question mark

bne $t1, $t2, upcase    # if it’s not a question mark, it was not a special character, try with upper case

setcap:                     # in any other case:

li  $t3,1               # next char must be capitalized

bnexti               # skip following comparisons and go to next char

upcase:

slti $t2,$t1,91         # if it’s less than 91 it could be an upper case (Z=90)

beq  $t2,$zero,lowcase  # if it was >= 90, it could be lowercase, go to next tests

slti $t2,$t1,65         # if it’s less than 65 it’s not an upper case (A=65)

bne  $t2,$zero,nexti    # if it’s less than 65, go to next char

bne  $t3,$zero,clrcap   # if it needs to be uppercase, it already is, clear flag

xori $t1,$t1,32         # if it needs to be lowercase, change from upper to lowercase

sb   $t1,0($t0)         # save changed letter in buffer

bnexti              # go to next character

lowcase:

slti $t2,$t1,123        # if it’s less than 123 it could be a lower case (z=122)

beq  $t2,$zero,nexti    # if it was >= 123, is not a letter, go to next char

slti $t2,$t1,97         # if it’s less than 97 it’s not a lower case (a=97)

bne  $t2,$zero,nexti    # if it’s less than 97, go to next char

beq  $t3,$zero,nexti    # if it needs to be lowercase, it already is, go to next char

xori $t1,$t1,32         # if it needs to be uppercase, change from lowercase to uppercase

sb   $t1,0($t0)         # save changed letter in buffer

clrcap:

li  $t3,0               # next char must not be capitalized

nexti:                                  #move to next character/iteration

addi $t0, $t0, 1      #i++

j     cloop                 #continue iterating through each character

return:

jr $ra