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

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

Related

How Read file "Comma Separated file" using Mips Assembly line by line then Char by Char and convert it from String of ASCII to Int?

enter image description here
the CSV file that i am trying to read
I am trying to read a CSV "Comma Separated file" In Mips assembly language, as string of ASCII then put it in Register or buffer as Integers .
If any one had the same problem or can help me with this .
I have tried to read a CSV file, put i couldn't continue .
.data
file: .asciiz "helloWorld.csv"
.word 0
buffer: .space 4
.text
main:
#open file
li $v0, 13
la $a0, file
add $a1, $zero, $zero
add $a2, $zero, $zero
syscall
add $s0, $v0, $zero
#read 4 bytes from file
li $v0, 14
add $a0, $s0, $zero
la $a1, buffer
li $a2, 4
syscall
#print
li $v0, 1
lw $a0, buffer
syscall
done:
li $v0, 16
add $a0, $s0, $zero
syscall
exit:
li $v0, 10
syscall

How do I continue my program after the "##"

So I have made a program which allows users to put how many hello world that they want and after ## there is another function but that won't play out instead the program just closes.
.data
n: .space 4
msg: .asciiz "Hello World"
prom1: .asciiz "How many Hello World want to be printed: "
mychar1:.byte 'a'
out_string: .asciiz "\nHello World\n"
prom: .asciiz "Type a number: "
mychar: .byte 'm'
res: .asciiz "Result is: "
nl: .asciiz "\n"
.text
main: li $v0, 4
la $a0, msg
syscall
li $v0, 4 # print str
la $a0, nl # at nl
syscall
li $v0, 4 # print str
la $a0, nl # at nl
syscall
li $v0, 4
la $a0, prom1 # Load address of first prompt
syscall
li $v0, 5 # Read int from user
syscall
li $t1, 0 # Load 0 into $t1 for comparison
move $t0, $v0 # Move the user input to $t0
loop:
beq $t1, $t0, end # Break If Equal: branch to 'end' when $t1 == $t2
li $v0, 4
la $a0, out_string # Load address of output string
syscall
add $t1, $t1, 1 # Increment $t1
j loop # Jump back up to loop
end:
li $v0, 10 # Load syscall 10 to indicate end of program
syscall
##
li $v0, 4 # print str
la $a0, nl # at nl
syscall
li $v0, 4 # print str
la $a0, prom # at prom
syscall
li $v0, 5 # read int
syscall
sw $v0, n # store in n
li $v0, 4 # print str
la $a0, res # at res
syscall
li $v0, 1 # print int
lw $t0, n # n
sub $t1, $t0, 1 # n-1
mul $t0, $t0, $t1 # *
sra $a0, $t0, 1 # /2
syscall
li $v0, 4 # print str
la $a0, nl # at nl
syscall
li $v0, 4 # print str
la $a0, nl # at nl
syscall
li $v0, 10 # exit
syscall
In this spot here
end:
li $v0, 10 # Load syscall 10 to indicate end of program
syscall
You are calling a syscall with 10 in the $v0 register.
This tells the computer to stop the program. So in this case you are just stopping the program before the rest of the code is executed.
Instead you could do this
loop:
beq $t1, $t0, endloop
li $v0, 4
la $a0, out_string # Load address of output string
syscall
add $t1, $t1, 1 # Increment $t1
j loop # Jump back up to loop
endloop:
# Put rest of code here
This is just the way to end the loop and continue.
Then at the end of the program you can put the syscall 10

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

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

A MIPS palindrome

The current code that I have looks as such. It can successfully read if a string is a palindrome when punctuation is not entered.
.data
buffer: .space 80
input: .asciiz "Enter a string: "
output: .asciiz "Your string: "
paly: .asciiz "This is a palindrome "
notp: .asciiz "This is not a palindrome"
.text
main:
li $v0, 4 # system call code for print_str
la $a0, input # address of string to print
syscall # print the input
li $v0, 8 # code for syscall read_string
la $a0, buffer # tell syscall where the buffer is
li $a1, 80 # tell syscall how big the buffer is
syscall
la $a0, buffer # move buffer into a0
li $v0, 4 # print buffer
syscall
la $t1, buffer # begining of the string
la $t2, buffer # end of the string
li $t0, 0
loop:
lb $t3,($t2) # load the byte of the end of the string
beqz $t3,endl # if its equal to 0 then branch out of the loop
addu $t2, $t2,1 # if in loop the increment to next character
jal loop # repeat the loop
upper:
addi $t4,$t4,32
j lowered
lowered:
addi $t0,$t0,1
sb $t4, 0($a0)
addi $a0,$a0,1
j loop
endl:
subu $t2, $t2, 2 # subtracting 2 to move back from \0 and \n
check:
#lb $t4, 0($a0)
#beqz $t4, after
#beq $t4, 10, after
#slti $t2, $t4, 91
#li $t3, 1
#beq $t2, $t3, upper
bge $t1, $t2, palindrome # if both sides are equal then its a palindrome
# call palindrome
lb $t3, ($t1) # load the byte into register t3
lb $t4, ($t2) # load the end byte into register t4
bne $t3, $t4, notpaly # if the two register bytes are not equal its it not a palindrome
addu $t1, $t1, 1 # increment the beginning of the string to next char
subu $t2, $t2, 1 # decrement end of string to next char to compare
jal check # repeat the loop
palindrome:
la $a0, paly # calling paly from data
li $v0, 4 # call for reading string
syscall
jal exit # jump to end
notpaly:
la $a0,notp # calling notp from data
li $v0, 4 # call for reading string
syscall
jal exit # jump to end
after:
li $v0, 4
la $a0, output
syscall
la $a0, buffer
li $v0, 4
syscall
exit:
li $v0 ,10 # call to end program
syscall # call os
Now I know I need to implement code such as to make uppercase lowercase, and to remove punctuation.
With my already stored bits in check: I have some commented code, and this would be to to test if a character is uppercase, then jump to the function and lower it by adding 32. But it does not compile correctly and i am assuming this is because I am not storing the bits correctly.
#lb $t4, 0($a0)
#beqz $t4, after
#beq $t4, 10, after
#slti $t2, $t4, 91
#li $t3, 1
#beq $t2, $t3, upper

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