Override string MIPS - mips

Have to copy the second string in the first, when the strings are the same size right but when the second is less complete with characters from the first in that space over. Follows the code. I am grateful if someone help.
.data
string1: .asciiz "Hello"
string2: .asciiz "Word"
finalStr: .space 256 # A 256 bytes buffer
buffer: .space 100
.text
main:
la $s1, finalStr
la $s2, string1
la $s3, string2
copySecondString:
lb $t0, ($s3) # get character at address
beqz $t0, exit
sb $t0, ($s2) # else store current character in the buffer
addi $s3, $s3, 1 # string1 pointer points a position forward
addi $s2, $s2, 1 # same for finalStr pointer
j copySecondString # loop
exit:
la $a0, string1
li $v0,4
syscall
li $v0, 10
syscall

The problem here is that you are not null terminating the string and hence it is bleeding over into the characters left over when the first string is longer than the second.
To fix this, move the check for null after the store instruction:
lb $t0, ($s3) # get character at address
sb $t0, ($s2) # store current character in the buffer
beqz $t0, exit # exit if null

Related

Swapping every two characters in a string and fixing exception error

I'm getting an exception error and I'm not sure why. I need some help with the fix for the exception and how to swap chars in the user inputted string?
The input and output should look something like this:
Input : Apples
Output : pAlpse
.text
main:
#Prompt user for string
la $a0, promptStr
li $v0, 4
syscall
#Get String
li $v0,8
la $a0, buffer
li $a1, 20
syscall
move $t0, $a0
#Initialize pointer to start of string (specify register)
la $t0, buffer
#Get a char from the string (register)
loop: lb $t1, ($t0)
I'm getting Instruction references undefined here and I have no idea why because I've used it in similar problems to branch out of a loop when at the end of a string.
Here's the error message
Instruction references undefined symbol at 0x00400058
[0x00400058] 0x11200000 beq $9, $0, 0 [strEnd-0x00400058]; 48: beqz $t1, strEnd
#IF at end of the string branch to endStr
beqz $t0, strEnd
#Add 1 to the string pointer
add $t0, 1#Fixed
#get the next char in the string
lb $t2, ($t0)
I don't know if this code is right. I just need help understanding
how to swap chars and what the code will look like.
#Swap the 2 chars by writing them back to the original string
sb $t2, ($t0)
sb $t1, ($t0)
#Add 1 to the string pointer
add $t0, 1 #Fixed
#Jump back to loopStart
j loop
#Display modified string
endStr: la $a0,ans
li $v0, 4
syscall
move $a0,$t2
li $v0, 4
syscall
#Blankline
la $a0, end
li $v0, 4
syscall
#Exit porgram
li $v0, 10
syscall
.data
buffer: .space 20
promptStr: .asciiz "Input a string : "
blankLine : .asciiz "\n"
The issue with your error beqz $t0, strEnd is a typo: the label you meant is endStr. The error itself tells you this, highlighting [strEnd-0x00400058] as undefined. Additionally, spim warns me on load:
The following symbols are undefined:
end
ans
After fixing the missing labels, the logic is not quite correct, although it looks like you're on the right track. The idea is to step over the string in character pairs, swapping elements and exiting when hitting a null character (and, optionally, a newline depending on how you want to handle that--stripping/chomping it is probably best).
For starters and a rather minor point, there is a dead instruction near the top of your program:
move $t0, $a0 # $t0 will be overwritten by the next la
#Initialize pointer to start of string (specify register)
la $t0, buffer
Stepping into the loop and the main logic, the code beqz $t0, strEnd uses the address of the string which will never be 0 as the branch condition rather than the byte at that address, $t1. This gives an infinite loop.
Next, there is a problem with $t0, the pointer that walks the string. The logic
sb $t2, ($t0)
sb $t1, ($t0)
doesn't work because $t0 was already incremented so the code loses track of the previous byte address after
#Add 1 to the string pointer
add $t0, 1#Fixed
A solution is to store $t0 in a temporary register before any add $0, 1 operations. Something like:
move $t3 $t0 # save the address of buf for swap
# ... later on, after incrementing `$t0` ...
sb $t2, ($t3)
sb $t1, ($t0)
You could also use an indexing strategy here by adding/subtracting offsets or using an index to walk the string.
Lastly, I'm not sure what move $a0,$t2 should do towards the end of the program when you're printing.
Here's one possible solution that addresses these issues and generally cleans up the logic:
.text
main:
# prompt user for string
la $a0 prompt
li $v0 4
syscall
# get string
la $a0 buffer
li $a1 20
li $v0 8
syscall
move $s0 $a0 # incrementable pointer to buf
loop:
# t1 = *(buf++) and exit if '\0' or '\n'
move $t0 $s0 # save the address of buf for swap
lb $t1 ($t0) # t1 = *buf
beqz $t1 end # break if '\0'
beq $t1 10 end # break if '\n'
add $s0 1 # buf++
# t2 = *buf and exit if '\0' or '\n'
lb $t2 ($s0) # t2 = *buf
beqz $t2 end # break if '\0'
beq $t2 10 end # break if '\n'
# swap the chars
sb $t2 ($t0) # *prev_buf = curr_buff_char
sb $t1 ($s0) # *buf = prev_buff_char
# increment pointer and continue to the next pair
add $s0 1 # buf++
j loop
end:
# display modified string
la $a0 buffer
li $v0 4
syscall
# exit program
li $v0 10
syscall
.data
buffer: .space 20
prompt: .asciiz "Input a string : "
Sample runs:
$ spim -f swap_alternating_chars.s
Input a string : Apple
pAlpe
$ spim -f swap_alternating_chars.s
Input a string : Apples
pAlpse

Understanding how string is stored in MIPS and how to count the number of characters in the string

I am a beginner in MIPS. To my understanding string is stored using directive .asciiz in MIPS, and each character in the string is stored in a byte. In order to obtain a specific character code (decimal) in the MIPS program, I will have to use lb (load byte) instruction, and specify the byte position of the string to get back the character decimal stored in that byte.
.text
main:
la $t0, str
move $a0, $t0
li $v0, 4 #print string
syscall
# ---------------------------
lb $a0, 0(t0) #to obtain the 1st character
li $v0, 1 #print it
syscall
# ---------------------------
li $v0, 10
syscall
.data
str: .asciiz "abcde"
If I need a program to count the number of characters in a string, the addi instruction is used which I don't seem to get it, shown in the program bellow :
.text
main:
la $t0, str
la $t1, 0 #counter
lb $a0, 0($t0) #set $a0 to 1st character in str
# ------------------------------
loop: beqz $a0, breakout #if character is empty = 0 (decimal) breakout
addi $t0, $t0, 1 # why?
addi $t1, $t1, 1 # to increment counter
lb $a0, 0($t0) #loads the first character in $t0
j loop
# ------------------------------
breakout: move $a0, $t1
li $v0, 1 #print counter
syscall
li $v0, 10 #system exit
syscall
.data
str: .asciiz "abcde"
I assume that "addi $t0, $t0, 1" will increment the address of $t0 by 1 from 268500992 to 268500993. Does that mean that an increment in the address by one will allow me to find the next character in the string, and that the increment of 1 in the address is equivalent to an increment of a byte in the address containing the string?
Many thanks!

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 - Printing a certain number of characters from a string

If given a number, I want to print out the first 'x' number of letters from the alphabet. I've setup a counter to determine the number of iterations the loop goes through, but I do not know how to extract the correct number of letters from the alphabet string.
Here's what I've done so far:
.data
alphabet:
.space 28
msg1: .ascii " Please enter an integer from 1-26:"
msg2: .ascii "abcdefghijklmnopqrstuvwxyz"
.text
.globl main
main:
li $v0, 5 # syscall for read_int
syscall
add $a0, $v0, $zero
li $t0, 0
li $t1, 26 # loop will start from zero and iterate to 26
loop:
la $t2, 0($a0)
beq $t0, $t2, end # once $t1 and $a0 are equal, loops stops
#li $t2, 1
#blt $t1, $t2, nomodify # do nothing if int less than 0
#li $t2, 26
#bgt $t0, $t2, nomodify # do nothing if int greater than 25
addi $t0, $t0, 1 # add 1 to $t1
j loop # jump back to top
end:
# Here is where I want to take 'x' number of iterations and convert it to
# the string of 'x' letters
li $v0, 10
syscall
Any help would be appreciated.
Having all the characters in a string is unnecessary for this task. Characters are integers, so you can just start at 'a' and count upwards:
# Assuming the loop count is in $t0
li $a0, 'a' # start at character 'a'
print_chars:
li $v0, 11
syscall # syscall 11 = print_character
addiu $a0, $a0, 1 # set $a0 to the next character
addiu $t0, $t0, -1
bne $t0, $zero, print_chars

I keep getting the bad address exception, any knows why?

I'm trying to do a simple program that counts the number of characters in a string . It seems I follow the structure but I keep getting the same bad address error, anyone knows why?
.data
array: .space 100
prompt1: .asciiz " Enter the string that you would like to reverse and calculate character: "
prompt2: .asciiz " "
.text
main:
la $a1, array # allocate the array space
ask:
li $v0, 4 # print String
la $a0, prompt1 # load prompt1
syscall
li $v0, 8 # read the string
syscall
move $a1, $v0 # move input to $a1
li $t0 ,0 # $t0 will hold the actual numbers of character in the string
loopCount:
lbu $t1, 0($a1) # load the next character into t1
beqz $t1, print # check for the null character
addi $a1, $a1, 1 # increment the string pointer
addi $t0, $t0, 1 # increment the count
b loopCount # return to the top of the loop
print:
li $v0, 1
move $a0, $t0
syscall
You should load the address of your buffer in $a0 and the size of the buffer in $a1 before the syscall to read the string.