write a mips code for finding and replacing a word in a sentence in MIPS architecture - mips

Develop a project that will search a word within the paragraph, and can perform the two different operations. One is to find the word present or not. Other one is to replace with another word of same size using MIPS.

got a program to find length of word see if it helps:
.data
string:
.asciiz "In a distant galaxy eons before the creation of the
mythical planet known as earth, vast civilizations have eveolved and
ruling the galaxy is an interstellar Empire created from the ruins of an
Old Republic that held sway for generations"
return:
.asciiz "\n"
wordcntmsg:
.asciiz "the word count of the length x \n"
newline:
.asciiz "\n"
wordlength:
.ascii " character word = "
.align 4
TABLE: .space 100
.text
.globl main
main:
la $t0, string # stores the address for string in $t0
la $s1, TABLE
addi $t2, $0, 32 # stores the ascii value for space in $t2
LOOP:
lbu $t1, 0($t0) # load the next charater
beq $t1, $0, DONE # END of STRING
nop
beq $t1,$t2,RESETWLC # space
nop
addi $s0,$s0,1 #inclement word length cnt.
addi $t0,$t0,1 #point next character.
j LOOP
nop
RESETWLC:
#inclement the word lenght cnt of that word length
# from the memory location.($s1)
# find memory location.
beq $s0,$0,PreviousSF
nop
# address computation
add $t3,$0,$s0 #
addi $t3,$t3,-1
sll $t3,$t3,2 # multiply 4 to get byte address.
add $t3,$t3,$s1 # get momory address.
lw $t4,0($t3) # get previous word length cnt from the memory.
addi $t4,$t4,1
sw $t4,0($t3) # inclement and store the cnt back.
add $s0,$0,$0 #reset word length cnt
PreviousSF:
addi $t0,$t0,1 #point next character.
j LOOP
nop
DONE: # print and Exit..
beq $s0,$0,PRINT
nop
# address computation
add $t3,$0,$s0 #
addi $t3,$t3,-1
sll $t3,$t3,2 # multiply 4 to get byte address.
add $t3,$t3,$s1 # get momory address.
lw $t4,0($t3) # get previous word length cnt from the memory.
addi $t4,$t4,1
sw $t4,0($t3) # inclement and store the cnt back.
PRINT:
la $a0, wordcntmsg
li $v0, 4
syscall
li $t0,26
li $t1,1
P_LOOP: move $a0,$t1
li $v0,1
syscall
la $a0,wordlength
li $v0,4
syscall
add $t3,$0,$t1 #
addi $t3,$t3,-1
sll $t3,$t3,2 # multiply 4 to get byte address.
add $t3,$t3,$s1 # get momory address.
lw $a0,0($t3) # get previous word length cnt from the memory.
li $v0,1
syscall
la $a0,newline
li $v0,4
syscall
addi $t1,$t1,1
beq $t1,$t0,EXIT
nop
j P_LOOP
nop
EXIT: addi $v0, $0, 10
syscall # Exits program
LB_SUB: #
add $t4, $0, $a0 #
srl $t4, $t4, 2 #
sll $t4, $t4, 2 #
sub $t5, $a0, $t4 #
addi $t7, $0, 8 #
mul $t6, $t5, $t7 #
lw $v0, 0($t4) #
addi $t8, $0, 24 #
sub $t8, $t8, $t6 #
sll $v0, $v0, $t8 #
srl $v0, $v0, 24 #
jr $ra #

.data
para: .space 1000 # Pre allocate space for the input paragraph
copypara: .space 1000 #copy the original paragraph
input: .space 30 # Pre allocate space for the input word
copy: .space 30 # Duplicate string to store the word
replace: .space 30 # The alternative word
replacemsg: .asciiz "Enter the word you want to replace with the word you want to find: \n" #display the msg to enter the alternative word
ask: .asciiz "Enter the paragraph:\n" # Display msg to enter the paragraph
askwd: .asciiz "Enter the word you want to find:\n" # Display msg to enter the word you want to find
nomatch: .asciiz "Sorry...The word is not present in the given paragraph.\n"
match: .asciiz "Number of times the word present in the paragraph is :-\n"
line: .asciiz "\n"
origpar: .asciiz "\nTHE ORIGINAL PARAGRAPH IS:- \n-----------------------------------------------------------------------------\n"
result: .asciiz "-----------------------------------------------------------------------------\nTHE MODIFIED PARAGRAPH IS:-\n-----------------------------------------------------------------------------\n"
error: .asciiz "Sorry...The word you you want to replace with is not the same size of the word you want to find.\n"
#======================================================================================================================================================================
#-----------------------------------------------------------------------------------------------------
# USE OF REGISTERS:
#
# $s5- Stores characters of copypara
# $t5- Stores ascii value of new line
# $s2- Stores characters of word to find
# $s4- Stores characters of word to replace
# $s0- Stores characters of copy,.i.e , the extracted word
# $s1- Stores characters of the entered paragraph
# $t4- Counts the number of characters in the word to find and also acts as a counter
# $t7- Stores the number of times the find word is found
# $t6- Counts the number of characters in the extracted word
# $t0- Stores the characters of the input paragraph and is also used in the case comparision
# $t8- Stores the characters of the input paragraph
# $t2- Stores the characters of the word to find and the extracted word
# $t3- Stores the characters of the extracted word and also used in case comparision
# $s7- Stores the numer of characters of the word to find and the extracted word that are equal
#
#----------------------------------------------------------------------------------------------------
.text
main:
# print the msg to enter the paragraph
li $v0,4
la $a0,ask
syscall
# Take the input paragraph
la $a0,para
li $a1,1000 # allocate 1000 empty space
li $v0,8
syscall
la $s5,copypara #load the the base address of the copypara
# print the msg to enter the word you want to find
li $v0,4
la $a0,askwd
syscall
# take the word
la $a0,input
li $a2,30 # create 30 empty spaces
li $v0,8
syscall
move $s2,$a0 # move the adress of the input word from $a0 to $s2
# print the msg to enter the word you want to replace
li $v0,4
la $a0,replacemsg
syscall
# take the word
la $a0,replace
li $a2,30
li $v0,8
syscall
move $s4,$a0 # the alternative word address is on $s4
# Assign the recquired ascii values in registers and load the base address of the recquired variables in their respective registers
li $t5,10 # ascii value of new line
la $s0,copy # loading the addresses of copy of extracted word and the original para
la $s1,para # loading the address of the paragraph
li $t4,1 # count the number of letters present in input word
li $t7,0 # count the number of times the word present
# Count the number of letters prsent in the input word
lb $t6,0($s2)
count:
beq $t6,10,countreplace
addiu $s2,$s2,1
lb $t6,0($s2)
addi $t4,$t4,1
j count
# This block count the number of letters present in replace word
countreplace :
la $s4,replace
li $t1,1
lb $t3,0($s4)
counting:
beq $t3,10,minor
addiu $s4,$s4,1
lb $t3,0($s4)
addi $t1,$t1,1
j counting
# This minor restores the variable containts in their respecive registers
minor:
li $t6,1 # count the number of letters present in the extracted word
la $s2,input # load the base address of the input word
lb $t0,0($s1) # loading the first character of the para
j extract
# This block stores the the replace word in place of the input word iff the word is found
store2:
la $s4,replace
li $t0,1
storing2:
beq $t0,$t4,intr
lb $t2,0($s4)
sb $t2,0($s5)
addiu $t0,$t0,1
addiu $s4,$s4,1
addiu $s5,$s5,1
j storing2
j intr
# This block is used to restore the original word present in the paragraph if the input word is not found
store1:
li $t0,1
la $s0,copy
storing1:
beq $t0,$t6,intr
lb $t2,0($s0)
sb $t2,0($s5)
addiu $t0,$t0,1
addiu $s0,$s0,1
addiu $s5,$s5,1
j storing1
# This block is used to re-initialize the register containt after one itteration
intr:
la $s4,replace
lb $t0,0($s1)
beq $t0,10,Display
la $s0,copy
li $t6,1
addiu $s1,$s1,1
lb $t0,0($s1)
sb $t8,0($s5)
addiu $s5,$s5,1
# This block is used to extract each word from the paragraph and store it in another variable called copy
extract:
lb $t8,0($s1)
beq $t0,32,compare
beq $t0,46,compare
beq $t0,10,compare
beq $t0,44,compare
beq $t0,40,compare
beq $t0,41,compare
beq $t0,39,compare
beq $t0,34,compare
beq $t0,45,compare
beq $t0,58,compare
beq $t0,59,compare
beq $t0,63,compare
beq $t0,33,compare
beq $t0,123,compare
beq $t0,125,compare
beq $t0,91,compare
beq $t0,93,compare
beq $t0,96,compare
beq $t0,95,compare
sb $t0,0($s0)
addi $t6,$t6,1
addiu $s0,$s0,1
addiu $s1,$s1,1
lb $t0,0($s1)
j extract
#Compare the extracted word and the input word
compare:
sb $t5,0($s0)
la $s2,input
la $s0,copy
lb $t2,0($s2)
lb $t3,0($s0)
bne $t6,$t4,store1
li $s7,0
check:
bne $t2,$t3,checkagain
backagain:
addi $s7,$s7,1
beq $s7,$t4,success
addiu $s2,$s2,1
addiu $s0,$s0,1
lb $t2,0($s2)
lb $t3,0($s0)
j check
# This block is used to handle the case sensitiveness of the program
checkagain:
addi $t3,$t3,32
addi $t0,$t3,-64
beq $t2,$t3,backagain
beq $t2,$t0,backagain
j store1
# This block is used to count the number of times the word is present in the paragraph
success:
addi $t7,$t7,1
j store2
# This block display the messeges according to their results
Display:
bne $t4,$t1,errormsg
beq $t7,0,msg
li $v0,4
la $a0,match
syscall
li $v0,1
la $a0,($t7)
syscall
li $v0,4
la $a0,line
syscall
li $v0,4
la $a0,origpar
syscall
li $v0,4
la $a0,para
syscall
li $v0,4
la $a0,result
syscall
li $v0,4
la $a0,copypara
syscall
j exit
msg:
li $v0,4
la $a0,nomatch
syscall
li $v0,4
la $a0,origpar
syscall
li $v0,4
la $a0,para
syscall
j exit
errormsg:
li $v0,4
la $a0,match
syscall
li $v0,1
la $a0,($t7)
syscall
li $v0,4
la $a0,line
syscall
li $v0,4
la $a0,error
syscall
li $v0,4
la $a0,origpar
syscall
li $v0,4
la $a0,para
syscall
# The exit block
exit:
li $v0,10
syscall

Related

MIPS: Trying to print a word from a file, always prints a letter

I'm pretty new to MIPS, hope you can help me. I need to write a program that gets some words from a file, which are separated by a character. I have written this code testing with just one word currently, but when it comes to printing the word (the print_word method), it's always printing the letter 'J', even if that letter is not on the word. What am I doing wrong here?
This is the code I currently have:
.data
origin: .asciiz "words.txt" # File containing the text, located on the same directory as the jar
messg: .asciiz "Please type a 1-character separator (, . |, etc): "
line: .space 1024 # Hard coded line size with max 1024 byte long
copy: .space 1024 # Space for the copied word
seprtr: .space 1 # Space for the separator
chartr: .space 1 # Space for the current character being read
newline: .asciiz "\n"
.text
main:
la $a0, messg
li $v0, 4 # Print message
syscall
la $a0, seprtr
li $a1, 1
li $v0, 8 # System call to read char
syscall
addi $s7, $v0, 0 # Save separator on $s7
jal new_line
la $s1, line
la $s2, copy
la $s3, chartr
read_line:
li $v0, 13 # Syscall to open file
la $a0, origin # File name
li $a1, 0 # Read
syscall #
add $s6, $zero, $v0 # Save file descriptor
str_read:
# Read file byte by byte
li $v0, 14 # Syscall to read file
add $a0, $zero, $s6 #
la $a1, chartr #
la $a2, 1 #
syscall #
move $t1, $v0
sb $t1, ($s2) # Concat the current byte
addi $s2, $s2, 1 #
beq $t1, $zero, print_word # If there's no more characters to read, skip to print word
beq $t1, $s0, print_word # If the current byte is the separator, skip to print word
j str_read # Otherwise, continue reading the word
print_word:
la $a0, ($s2) # Load address of the 'copied' word
li $v0, 4 # Show word
syscall
j exit
new_line:
la $a0, newline # Print a new line
li $v0, 4
syscall
jr $ra
exit:
li $v0, 10 # Exit the program
syscall
This is
the answer it's always printing

How to count the number of words and print the result in mips?

So I am fairly new to mips and am trying to do a hmwk.
The exercise is to create a block of words with 0 as the last word , to count them knowing we don't consider the last element 0 and print out the result.
Here is my code for the moment
.data
blockOfWords: .word 12,43,549,7,60,0
.text
la $a0, blockOfWords #putting address of blockOfWords in $a0
loopStart: sll $t1, $s3,2 #iterates thru blockOfWords by jumping by 4 bytes, $t1=4*i
add $t1,$t1,$a0 #we increment the address by four so as to advance in the array after every iteration
lw $a1, 0($t1) #$a1=blockOfWOrds[i]
beq $a1,$zero, Exit #if the value in $a1[i]==0, exit the loop
addi $s0,$s0,1 #else, increment by one the cnt=$s0
j loopStart #and continue looping thru blockOfWords
Exit:
#how do i print the result?
So instead of doing a shift left logical it is a lot easier to up the memory address in the array
In this way the lw $a1, 0($a0) is just grabbing the beginning of the word
it is then incremented by 4 after a check for the 0. This makes the function much simpler and easier to read.
.data
blockOfWords: .word 12,43,549,7,60,0
.text
main:
la $a0, blockOfWords # Load beginning address into $a0
loopStart:
lw $a1, 0($a0) # load the value at the beginning of $a0 into $a1
beq $a1,$zero, exit # Check if $a1 is 0, if so jump to exit
addi $s0,$s0,1 # Add one to the count
addi $a0, $a0, 4 # Up the intial index of the array by 4, up one word
j loopStart # Re-loop
exit:
li $v0, 1 # Load the value of 1 into the $v0 register
la $a0, ($s0) # Load the counter into the $a0 address
syscall
li $v0, 10 # A value 10 syscall to indicate end of program
syscall

How to store the input correctly in MIPS?

Although I have try to input different value ,but the Qtspim still print out the value"0" and the input is also not saved in the register ,I try to find the answer in internet,but it seem like no one have face this problem before.I do it work for 4hrs, I FEEL very frustrated with this.
here is my code ,I try to define whether the input is prime number or not.
# Power program
# ----------------------------------
# Data Segment
.data
request: .asciiz "Enter an integer:"
Yes: .asciiz " is a prime number.\n"
No: .asciiz " is not a prime number\n."
End: .asciiz"End!\n"
Key: .word -1
One: .word 1
# ----------------------------------
# Text/Code Segment
.text
.globl main
main:
lw $t1,One
add $s2,$zero,$zero
lw $s3,One
lw $s0,Key
add $s5,$zero,$zero
j power # call the function power
li $v0, 10 # call code for exit
syscall # system call
.end main
.globl power
power:
j power_loop
power_loop:
la $a0, request # load string request in memory to $a0
li $v0, 4 # print out the string
syscall #prevent Memory address out of bounds
li $v0, 5
syscall
move $s7,$v0
beq $s7, $s0, exit_L #when input =-1 exit
j Prime #otherwise go to define the input whether prime num
Prime:
beq $s7,$t1,result
div $s7,$t1
mthi $t4
beq $t4,$zero,count
addi $t1,$t1,1
j Prime
count: #counting the number of factors
addi $s2,1
addi $t1,$t1,1
result: addi $t1,$zero,1
bne $s2,$s3,resultNo
beq $s2,$s3,resultYes
resultYes: li $v0,1
move $a0,$s7
syscall
add $s2,$zero,$zero
la $a0,Yes
li $v0,4
syscall
j power_loop
resultNo: li $v0,1
move $a0,$s7
syscall
add $s2,$zero,$zero
la $a0,No
li $v0,4
syscall
j power_loop
exit_L:
la $a0,End
li $v0,4
syscall
jr $ra
.end power

Taking in a String, cutting the first character, then converting to int

The code I'm working on takes in a string from the user in the form "X123" (not limited to 3 characters) where X can be any non-number character, and 123 can be any series of number characters. The code then strips the non-number, converts the number part to an int, adds 5, and prints the result.
.data
msgerror: .asciiz "The string does not contain valid digits."
input: .space 9
open: .asciiz "Enter a string:\n"
close: .asciiz "The value +5 is:\n"
.text
.globl main
main:
li $v0, 4
la $a0, open
syscall
li $v0, 8
la $a0, input #read a string into a0
move $t0, $a0
syscall
li $t3,0
li $t4,9
la $t0, input #address of string
lbu $t1, 1($t0) #Get first digit of actual number
li $a1, 10 #Ascii of line feed
li $a0, 0 #accumulator
addi $t1,$t1,-48 #Convert from ASCII to digit
move $a2, $t1 #$a2=$t1 goto checkdigit
jal checkdigit
add $a0, $a0, $t1 #Accumulates
addi $t0, $t0, 1 #Advance string pointer
lbu $t1, ($t0) #Get next digit
buc1:
beq $t1, $a1, print #if $t1=10(linefeed) then print
addi $t1,$t1,-48 #Convert from ASCII to digit
move $a2, $t1 #$a2=$t1 goto checkdigit
jal checkdigit
mul $t2, $a0, 10 #Multiply by 10
add $a0, $t2, $t1 #Accumulates
addi $t0, $t0, 1 #Advance string pointer
lbu $t1, ($t0) #Get next digit
b buc1
print:
add $a0, $a0, 5
li $v0, 1
syscall
b end
checkdigit:
blt $a2, $t3, error
bgt $a2, $t4, error
jr $ra
error:
la $a0, msgerror
li $v0, 4 #print eror
syscall
end:
li $v0, 10 #end program
syscall
However, my code ends up producing:
Enter a string:
x123
The value +5 is:
1128
(128 is the expected).
How can I make one of the duplicate numbers go away? I've tried incrementing the address by 1 with print statements, but it seems not to work with anything else/not as intended.
li $v0,4
la $a0, aString
add $a0, $a0, 1
syscall
The above snippet produces 23 if 123 is entered, but I can't get it to apply to the above.
Easier overall approaches are welcome too. New to mips, so I hardly think mine is all that great.
Looks like you read the first digit twice.
This part:
li $t3,0
li $t4,9
la $t0, input #address of string
lbu $t1, 1($t0) #Get first digit of actual number
Should be changed to:
li $t3,0
li $t4,9
la $t0, input+1 #address of first digit in string
lbu $t1, ($t0) #Get first digit of actual number

MIPS Calculator

I'm trying to finish up this MIPS calculator, super basic, my first mips program. It doesn't have to handle overflow or anything like that, just has to work on small, positive numbers.
I've not checked my algorithms for multiply and divide, because I am just trying to get add working.
I cannot for the life of me figure out why the ints will not read in and also I'm getting a memory out of bounds when I call lb $a0, op to display the operator for output and don't understand why.
I'm new to this so anything is probably helpful. Thanks in advance.
.data
# const string for welcome
welc: .asciiz "Welcome to SPIM Calculator 1.0!\n"
p_int: .asciiz "\nPlease give an integer: "
p_op: .asciiz "\nPlease give an operator: "
i_err: .asciiz "\nInput Incorrect, bad operator!\n"
again_str: .asciiz "Another calculation? (y/n)"
rmndr: .asciiz " r: "
new_line: .asciiz "\n"
int1: .word 1 # space to hold int 1
int2: .word 1 # space to hold int 2
raw_in: .space 1 # space to hold raw input
op: .space 1 # space to hold operator char
a_char: .space 1 # space to hold again char
out: .word 1 # space to hold output
remain: .word 1 # space to hold remainder
#operator constants
c_plus: .ascii "+" # const for +
c_min: .asciiz "-" # const for -
c_mult: .asciiz "*" # const for *
c_divi: .asciiz "/" # const for /
c_eq: .asciiz "=" # const for =
c_no: .asciiz "n" # const for n
.text
.globl main
main: li $v0, 4 # syscall 4, print string
la $a0, welc # give argument: string
syscall # actually print string
calc: la $t6, remain # load remainder variable
move $t6, $zero # store 0 in remainder (reset)
li $v0, 4 # syscall 4, print string
la $a0, p_int # give argument: string
syscall # actually print string
li $v0, 5 # tell syscall we want to read int 1
syscall # actually read in int 1
la $s1, int1 # load int1 into $s1
move $s1, $v0 # copy the integer from $v0 to int1
li $v0, 4 # syscall 4, print string
la $a0, p_int # give argument: string
syscall # actually print string
li $v0, 5 # tell syscall we want to read int 2
syscall # actually read in int 2
la $s2, int2 # give $s2 the address to hold int 2
move $s2, $v0 # copy the integer from $v0 to $s2
li $v0, 4 # syscall 4, print string
la $a0, p_op # give argument: string
syscall # actually print string
li $v0, 8 # tell syscall we want to read operator
la $a0, op # give $a0 the address to hold the operator
syscall # actually read in operator
lb $t0, op # load the first byte of op
li $t1, '+' # load const for plus
li $t2, '-' # load const for minus
li $t3, '*' # load const for multiplying
li $t4, '/' # load const for dividing
la $s0, out # load out to $s0
beq $t0, $t1, plus # we're adding
beq $t0, $t2, minus # we're subtracting
beq $t0, $t3, multi # we're multiplying
beq $t0, $t4, divi # we're dividing
# else
j error # incorrect input
plus: add $s0, $s1, $s2 # add our ints, store in $t0
j print
minus: sub $s0, $s1, $s2 # subtract our ints, store in $t0
j print
multi: slt $t1, $t2, $s2 # if our counter is less than int2, set $t1 to 1
beq $t1, $zero, print # if we've reached int2, we're done
add $s0, $s1, $s1 # add int1 and int1, store in out
j multi # loop
divi: la $t0 remain # load remainder into $t0
move $t0, $s1 # set remainder to dividend
add $s0, $zero, $zero # set out to 0, just in case
loop: slt $t1, $t0, $s2 # if remainder is less than divisor, set 1
beq $t1, $zero, print # if we're done branch to done
sub $t0, $t0, $s2 # sub divisor from remainder, store in remainder
addi $s0, $s0, 1 # increment quotient by 1
j loop # loop
print: li $v0, 1 # tell syscall we want to print int
la $a0, int1 # give syscall int1 to print
syscall # actually print int
li $v0, 4 # tell syscall we want to print string
lb $a0, op # tell syscall we want to print operator
syscall # actually print string
li $v0, 1 # tell syscall we want to print int
la $a0, int2 # give syscall int2 to print
syscall # actually print int
li $v0, 4 # tell syscall we want to print string
la $a0, c_eq # tell syscall we want to print operator
syscall # actually print string
li $v0, 1 # tell syscall we want to print integer
la $a0, out # give syscall our output
syscall # actually print int
la $t0, remain # load remainder
beq $t0, $zero, again # if we have no remainder, finish printing
li $v0, 4 # tell syscall we want to print string
la $a0, rmndr # tell syscall we want to print remainder string
syscall # print "r: "
li $v0, 1 # tell syscall we want to print int
la $a0, remain # give syscall our remainder to print
syscall # print remainder
again: li $v0, 4 # tell syscall we want to print string
la $a0, new_line # tell syscall to print new line
syscall
la $a0, again_str # load prompt for again string for syscall
syscall
li $v0, 8 # tell syscall we want to read string
la $a0, a_char # tell syscall to put it in $a0
syscall
lb $t0, a_char
li $t1, 'n' # get n char so we can compare
beq $t0, $t1, exit # if we are done, exit
#else loop
j calc # jump to beginning
error: li $v0, 4 # tell syscall we want to print string
la $a0, i_err # give syscall what to print
syscall # actually print
j again # go to prompt for retry
exit: li $v0, 10 # exit code
syscall #exit!
screenshot
The problem is that you don't use the appropriate instruction to handle memory.
Instead of move you should use sw (store word). This code will not store the int into int1:
la $s1, int1 # load int1 into $s1
move $s1, $v0 # copy the integer from $v0 to int1
instead, you should write:
la $s1, int1 # load address of int1 into $s1
sw $v0, 0($s1) # copy the integer from $v0 to int1
Like storing, loading from memory require two instructions:
la $s1, p_op # or whatever register you choose to use
lb $a0, 0($s1) # load byte from the address stored in $s0 (in index 0)
if you want to load the address of p_op into $a0, you should use la $a0, p_op, not lb