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: