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

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 :\

Related

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).

MIPS, how to get 5 strings from console and then print them out

# Data section
.data
insert1: .word 20 # make space in memory for a word with address insert1
insert2: .word 20
insert3: .word 20
insert4: .word 20
insert5: .word 20
Input: .asciiz "Enter a Series of 5 formulae\n"
Output: .asciiz "The values are:\n"
CR: .asciiz "\n"
# Text Section
.text
.globl my_main
my_main:
la $a0, Input
li $v0, 4
syscall
la $a0, insert1 # sets $a0 to point to the space allocated for writing a word
la $a1, insert1 # gets the length of the space in $a1 so we can't go over the memory limit
li $v0, 8
move $t0, $a0
syscall
la $a0, insert2
la $a1, insert2
li $v0, 8
li $v0, 8
move $t1, $a0
syscall
la $a0, insert3
la $a1, insert3
li $v0, 8
li $v0, 8
move $t2, $a0
syscall
la $a0, insert4
la $a1, insert4
li $v0, 8
li $v0, 8
move $t3, $a0
syscall
la $a0, insert5
la $a1, insert5
li $v0, 8
li $v0, 8
move $t4, $a0
syscall
la $a0, Output
li $v0, 4
syscall
la $a0, insert1
li $v0, 4
syscall
la $a0, insert2
li $v0, 4
syscall
la $a0, insert3
li $v0, 4
syscall
la $a0, insert4
li $v0, 4
syscall
la $a0, insert5
li $v0, 4
syscall
# Exits Program
li $v0, 10
syscall
Results I'm getting:
Enter a Series of 5 formulae:
hey
man
how
are
you
The values are:
hey
man
how
are
you
man
how
are
you
how
are
you
are
you
you
Results I want:
Enter a Series of 5 formulae:
hey
man
how
are
you
The values are:
hey
man
how
are
you
So basically I need to take 5 strings from the console and then print out as seen above. Weirdly enough when I use words that are only 1 letter long it prints out correctly but anything else other than single letters returns a sequence of words similar to what I've shown above. I'm new to MIPS and not sure what I'm doing wrong here. Any help would be appreciated thanks.
EDIT: It seems I just needed to use .space instead of .word. Thanks to those who commented/answered the question for helping out.

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.

MIPS Print String that was red without BREAKS

.data:
str2: .space 20
#read string
la $a0,str2
li $a1,20
li $v0,8
syscall
#print string
la $a0, str2
li $v0, 4
syscall
#print string
la $a0, str2
li $v0, 4
syscall
The result:
EXAMPLETEX
(I DONT WANT THIS BREAK... HOW DO I REMOVE IT?)
EXAMPLETEXT
-- program is finished running (dropped off bottom) --
Your problem is that service 8 adds a newline at the end of the input string, so you have to replace it with a null byte (0)
Add this code after the syscall that reads str2:
# remove trailing newline
li $a3, '\n'
newlineloop:
beqz $a1, newlineloopend
subu $a1, $a1, 1
lb $a2, str2($a1)
bne $a2, $a3, newlineloop
li $a3, 0
sb $a3, str2($a1)
newlineloopend:
It will search for that newline character and replace it with a null byte

Resources