How to store/read string on MIPS? - string

I'm having trouble reading a string that previously was introduced by the user and saved in memory.
The function to read the string:
.data
table: .space 1200
buffer: .space 30
empty: .asciiz "The string is empty\n"
.text
la $t7,table
li $s4,0
li $v0, 8
la $a0,buffer
li $a1, 30
syscall
move $t0,$a0
move $a0,$t0 # parameter
jal insert
Then using the readed string, I pass through $a0 as a parameter to another function that stores the string to a certain memory position (with 60 bytes space within each string).
insert: mul $s6,$s4,60 # padding (index*padding)
add $t7,$t7,$s6 # address of the next free position
sw $a0,0($t7)
addi $s4,$s4,1
Also I've got a function that given an index (introduced by the user as an integer), recovers the string stored in that position (if is not empty):
read_table: move $t5,$a0 # a0 contains the index as a parameter
la $t4, table
mul $t5,$t5,60
add $t4,$t4,$t5
lw $s1,0($t4)
beqz $s1,empty_str
li $v0,4
move $a0,$s1
syscall
empty_str: li $v0,4
la $a0,empty
syscall
My problem comes when regardless of the index I enter, the program always return the last string introduced by the user although it seems to be stored properly. I understand that it might be some misuse of the buffer, but any of the solutions I've thought worked.
[EDIT] Here goes the whole code block to clarify the question, as suggested (supposing that all the data that the user introduces is OK):
):
.data
table: .space 1200
buffer: .space 30
empty: .asciiz "The string is empty\n"
.text
la $t7,table
li $s4,0
main: li $v0,4
la $a0,tira1
syscall
li $v0,5
syscall
beqz $v0,index # If 0, read from table, 1 insert to the table
beq $v0,1,string
string: li $v0, 8
la $a0,buffer
li $a1, 30
syscall
move $t0,$a0
move $a0,$t0 # parameter
jal insert
index: li $v0,5 # function to get index
syscall
move $a0,$v0
jal read_table
insert: mul $s6,$s4,60 # padding (index*padding)
add $t7,$t7,$s6 # address of the next free position
sw $a0,0($t7)
addi $s4,$s4,1
b main
read_table: move $t5,$a0 # a0 contains the index as a parameter
la $t4, table
mul $t5,$t5,60
add $t4,$t4,$t5
lw $s1,0($t4)
beqz $s1,empty_str
li $v0,4
move $a0,$s1
syscall
b main
empty_str: li $v0,4
la $a0,empty
syscall

Related

Separate words of the string and store them in stack in MIPS

.data
string: .asciiz "Please enter the string : "
newLine: .asciiz "\n"
buffer: .space 100
.text
.globl main
main:
la $a0, string
li $v0, 4
syscall
li $v0, 8
la $a0, buffer
li $a1, 100
syscall
la $t0, buffer
li $t0, 0
subu $sp, $sp, 4
li $v0, 4
syscall
Here above is beginning of the my code. And I need to separate each words of the string and then store them in the stack. First I tried to store word in stack as allocation memory with stack pointer and it works now. But I need to store each word(not characters) of the sentence such as
Hello I am Furkan
So for this example there should be 4 words in stack.
Hello
I
am
Furkan
How can I solve that ?

Can't write to file more than once in MIPS?

I'm currently trying to learn how to write to files, however I can't seem to write to a file more than once. How would I go about writing multiple strings to a file, or in this case, the same string more than once? Thanks.
.data
str_exit: .asciiz "test.txt"
str_data: .asciiz "This is a test!"
str_data_end:
.text
file_open:
li $v0, 13
la $a0, str_exit
li $a1, 1
li $a2, 0
syscall # File descriptor gets returned in $v0
file_write:
move $a0, $v0 # Syscall 15 requieres file descriptor in $a0
li $v0, 15
la $a1, str_data
la $a2, str_data_end
la $a3, str_data
subu $a2, $a2, $a3 # computes the length of the string, this is really a constant
syscall
move $a0, $v0 # Syscall 15 requieres file descriptor in $a0
li $v0, 15
la $a1, str_data
la $a2, str_data_end
la $a3, str_data
subu $a2, $a2, $a3 # computes the length of the string, this is really a constant
syscall
file_close:
li $v0, 16 # $a0 already has the file descriptor
syscall
I've been trying to figure this out for over half an hour yet the minute I post a question I figure it out on my own. I was setting $a0 to $v0, which had the incorrect value in it as I used $v0 after the first syscall, meaning I had the incorrect value in $a0 :\

MIPS - How do i concatenate User Input Strings and print them out after reading consecutive "\n" "\n"?

I have a function called saisir that needs to take in user input text and lets you enter \n 's in the input as part of the text. It returns the text that was entered by the user avec reading \n\n.
.data
buffer: .space 300
msg: .asciiz "You entered:\n"
.text
main: #calling the function
jal saisir
li $v0,10 #end the program
syscall
saisir:
li $v0,8 #take in input
la $a0, buffer #address where we store buffer
li $a1, 300
syscall
li $t0, 0
lb $t0, ($a0)
li $t1, 10 #\n caracter in ASCII
bne $t0, $t1, saisir
#Displays "You entered:"
li $v0, 4
la $a0, msg
syscall
#Displays User's input
li $v0, 4
la $a0, buffer
syscall
jr $ra #goes back
The code written right now overwrites every line of text entered by the user, therefore returns a string that is empty.. How to add the strings up as you would in a high level language with "+=" in MIPS?

String input in MIPS omits the first four characters that are inputted

.data
EntryReq:
.asciiz "Please enter an 8 digit hexadecimal MIPS instruction: \n"
InputLongError:
.asciiz "\nYour input was too long, make sure it is 8 digits. "
InputShortError:
.asciiz "\nYour input was too short, make sure it is 8 digits. "
CharInvalidError:
.asciiz "\nYour input contains an invalid character. "
ValidChars:
.asciiz "0123456789abcdef\n\b\0"
.align 4
input:
.space 20
.text
main:
#Print input request
la $a0, EntryReq #loads input into arg. reg.
li $v0, 4 #op code for print string
syscall
#take input for input (stored)
li $v0, 8 #op code for take user input
la $a0, input #provide address for syscall
li $a1, 20 # tell syscall the byte space required for the string
syscall
#move to input(stored)
sw $v0, input #move inputted into from $v0 to input(stored)
#check validity of input
la $a0, input #load address of input to arg. reg. for method call
la $a1, ValidChars #load address of string of valid chars
jal verifyInput #call the verifyInput method which does as expected
#test if string length count works
addi $a0, $v0, 0 #load from $v0 to arg. reg.
li $v0, 1 #op code for print int
syscall
terminate:
li $v0, 10
syscall
verifyInput:
li $v0, -1 #start length count at 0
verifyLoop:
lb $t0, ($a0) #load current
li $a2, 0 #loop for char check, loops up to length of validChar string
la $a1, ValidChars
j checkChar
charVerified: #ignore this, is entry point back into verifyLoop for checkChar
addi $a0, $a0, 1 #increment
addi $v0, $v0, 1
bgt $v0, 8, printTooLongError #if result bigger than 8, error
bne $t0, 10, verifyLoop #10 is string end, so check if string is end
blt $v0, 8, printTooShortError #if result less than 8, error
jr $ra #if here string input was confirmed okay
checkChar: # loops through valid chars for each char in $a0 | Valid Chars: 0123456789abcdef\n |
lb $t1, ($a1) #loads in byte from char string
addi $a1, $a1, 1 #increment address, for the next char
addi $a2, $a2, 1 #increment until length of valid char string is reached
beq $t0, $t1, charVerified
bne $a2, 19, checkChar #if length of valid chars changes, change second argument here
j charNotValidError
charNotValidError:
la $a0, CharInvalidError #loads input into arg. reg.
li $v0, 4 #op code for print string
syscall
j terminate
printTooLongError:
la $a0, InputLongError #loads input into arg. reg.
li $v0, 4 #op code for print string
syscall
j terminate
printTooShortError:
la $a0, InputShortError #loads input into arg. reg.
li $v0, 4 #op code for print string
syscall
j terminate
The general gist of this code is for the user to input an 8 digit hexadecimal string, and then the program checks whether it is a valid hexadecimal string (i.e. includes only 0-9 and a-f). However, whenever I run it, the string that I input is missing the first four characters. So if I place invalid characters in the first four digits, like wwww1abc, then the code runs fine, which it shouldn't. But if I do 1abcwwww, it outputs an invalid character error, which it should. I'm genuinely confused as to why this is the case, nor have I seen anyone else experience this issue. Any help is greatly appreciated.
The problem is this line:
#move to input(stored)
sw $v0, input #move inputted into from $v0 to input(stored)
Unlike read integer syscall, read string puts the result in the input buffer, in your case input. So you don't need to read out the value in $v0 and by storing it in input you're overwriting the first 4 bytes of the buffer with the value of $v0, which is still 0x00000008, which conveniently is the same as the string "\b\0\0\0" for little endian machines, all of which are in your validity list. Removing that line should fix your program (though I didn't look over all the rest of the code for errors).

Push Each Character of a String Into a Stack MIPS

So I'm working on a project in MIPS to check if a string input by the user is a palindrome or not. The part I'm stuck on is reading the string and pushing each character of the string into the stack one by one (the PushLoop part of the code). When I debug it, the program seems to think I haven't entered anything at all. Here's what I have so far:
.text
main:
li $v0, 4 # Prints str1
la $a0, str1
syscall
jal Init # Sets $s0 equal to $sp to compare if the stack is empty later
li $v0, 8 # Read String
la $a0, buffer # Loads memory buffer (100)
li $a1, 100 # Defines length of buffer
syscall
la $t0, buffer # Moves base register to $t0
PushLoop:
lb $a2, ($t0) # Loads current character into $a2
beqz $a2, fin # if $a2 is equal to zero, the loop is terminated
jal Push # Pushes what is stored in $a0 to the stack
add $t0, $t0, -8 # Subtracts from buffer
j PushLoop
fin:
la $t0, buffer # Resets the memory buffer (I think)
PopLoop:
jal IsEmpty # Checks if the stack is empty
lb $a2, ($t0) # Loads current character into $a2
beq $v0, 1, isPal # If stack is empty, jump to isPal
jal Pop # Pops what is stored in the stack to $t1
add $t0, $t0, -8 # Subtracts from buffer
bne $a2, $t1, notPal
j PopLoop
notPal:
li $v0, 4 # Prints str3
la $a0, str3
syscall
li $v0, 0 # loads 0 into $v0
j end
isPal:
li $v0, 4 # Prints str2
la $a0, str2
syscall
li $v0, 1 # loads 1 into $v0
j end
#EXIT
end:
li $v0, 10 # ends the program
syscall
Push:
addi $sp, $sp, -8 # Move stack pointer
sb $a2, ($sp) # Store contents of $a2 at ($sp)
jr $ra
Pop:
lw $t1, ($sp) # Pop char from stack and store in $t1
addi $sp, $sp, 8 # Move stack pointer
jr $ra
Init:
add $s0, $sp, $zero # Sets $s0 equal to $sp
jr $ra
IsEmpty:
beq $sp, $s0, Yes # If $s0 is equal to the initial value of $sp, then stack is empty
li $v0, 0 # Loads 0 into $v0
jr $ra
Yes:
li $v0, 1 # Loads 1 into $v0
jr $ra
.data # Data declaration section
str1: .asciiz "Please enter a String: "
str2: .asciiz "Is a palindrome!"
str3: .asciiz "Is NOT a palindrome"
buffer: .space 100
I'm sure there are more things wrong with the code, but I'm just trying to squash one bug at a time. Thanks so much for helping me out!
You're not using syscall 8 properly:
li $v0, 8 # Read String
la $t0, buffer # Loads memory buffer (100)
syscall
If you read the description of syscall 8, it says "Arguments $a0 = buffer, $a1 = length". So those three lines of code should be changed into something like:
li $v0, 8 # Read String
la $a0, buffer
li $a1, 100
syscall
Then you can do la $t0, buffer after the syscall if you still want to use $t0 as the base register for the memory reads in PushLoop.

Resources