Removing spaces in a string, MIPS assembly - string

I have a small problem with a program i'm trying to write. Basically i'm prompting a user for input. I then count the number of spaces in the string, and display the count. I also need to print out the original string with spaces removed.
The bug I'm having is when i'm adding characters to my string without spaces, it only adds the first character. $t2 is the register that is holding the character to be added, and I've checked the registers during run-time to be sure the value there was changing. I don't know where else to look.
.data
str: .space 81 # buffer for input string
strNS: .space 81 # buffer for string w/o spaces
prompt: .asciiz "Enter a string up to 80 characters\n"
head1: .asciiz "\nOriginal String: "
head2: .asciiz "\nNumber of spaces: "
head3: .asciiz "\nWith spaces removed: "
.text
main:
#print the first prompt and get the input string from console
li $v0, 4 #load syscall value to print string into $v0
la $a0, prompt #address of prompt to print
syscall #print prompt to console
li $v0, 8 #load syscall value to read input string
la $a0, str #addr of allocated space for input string is now in $a0
li $a1, 81
syscall
jal countSpace
addi $t1, $v0, 0 #the count of spaces is in $v0, save it into $t1
li $v0, 4 #print header then the count
la $a0, head1
syscall
la $a0, str #print the original string
syscall
la $a0, head2 #print second header before printing count
syscall
li $v0, 1
addi $a0, $t1, 0 #place the count in $a0
syscall #print the count
li $v0, 4
la $a0, head3 #print the third header
syscall
la $a0, strNS #print no spaces string
syscall
End:
li $v0, 10 #load syscall value for exit
syscall #exit
countSpace:
la $s0, strNS
addi $sp, $sp, -12 #adjust the stack pointer for saving
sw $s0, 8($sp) #store addr of nospace string
sw $ra, 4($sp) #store return addr on the stack
sw $a0, 0($sp) #store the count on the stack
#Begin counting spaces
addi $t3, $a0, 0 #$t3 has addr of user input
addi $t5, $s0, 0 #$t5 has addr of string with no spaces
li $t6, 0 #$t6 holds index of string with no spaces
li $t0, 0 #$t0 will hold the count of spaces
li $t4, 0 #$t4 holds the index of the string
loop:
add $t1, $t3, $t4 #$t1 = addr of str[i]
lb $t2, 0($t1) #$t2 = character in str[i]
beq $t2, $zero, exitCS #break from loop if $t2 contains null character
addi $a0, $t2, 0 #place value to be checked in $a0
#save values onto stack from temp registers to preserve them
addi $sp, $sp, -28 #adjust the stack pointer for 5 values
sw $t6, 24($sp) #save index of string with no spaces
sw $t5, 20($sp) #save addr of string with no spaces
sw $t4, 16($sp) #save index of user input
sw $t3, 12($sp) #save the addr of user input
sb $t2, 8($sp) #save the character in str[i]
sw $t1, 4($sp) #save the address of str[i]
sw $t0, 0($sp) #save the count of spaces
jal isSpace #result from this jump and link will be in $v0 after call
#pop saved values from the stack, then reset the pointer
lw $t6, 24($sp)
lw $t5, 20($sp)
lw $t4, 16($sp)
lw $t3, 12($sp)
lb $t2, 8($sp)
lw $t1, 4($sp)
lw $t0, 0($sp)
addi $sp, $sp, 28 #reset stack pointer
beq $v0, $zero, addTo #if not a space, continue to next character
addi $t0, $t0, 1 #if it is a space, increment count
addTo:
bne $v0, $zero, nextChar #If character is a space, branch
sll $t7, $t6, 2 #index if nospaces string stores width of 4
add $t7, $t7, $t5 #now $t7 points at nospaces[i]
sb $t2, 0($t7) #store the character in the nospaces string
addi $t6, $t6, 1 #increment the index of nospaces
nextChar:
addi $t4, $t4, 1 #increment the index value
j loop #jump back to loop and continue processing
exitCS:
addi $v0, $t0, 0 #count of spaces placed into $v0
addi $v1, $t5, 0
lw $ra, 4($sp) #load return addr from the stack
lw $a0, 0($sp) #load value to check from the stack
addi $sp, $sp, 8 #reset stack pointer
jr $ra #return
isSpace:
addi $sp, $sp, -12 #adjust stack pointer to make room
sw $s0, 8($sp)
sw $ra, 4($sp) #store value of return addr onto stack
sw $a0, 0($sp) #store value to check onto stack
#Check to see if the character is a space
li $t0, 32 #ascii value for space character loaded into $t0
li $v0, 0 #Set default return to 0, or "not a space character"
bne $t0, $a0, endSC #if ascii values match, character is a space
li $v0, 1 #$v0 = 1 means it is a space character
endSC:
lw $s0, 8($sp)
lw $ra, 4($sp) #restore return address
lw $a0, 0($sp) #restore addr of str
addi $sp, $sp, 12 #reset the stack pointer
end: jr $ra

Change sll $t7, $t6, 2 to move $t7, $t6. There's no need to align anything manually.
Here's the data segment of your program after a run with the input here's some spaces. Once you see the bug, the fix should be obvious.

Related

Reason why I am having garbage values appear?

So when I call this function for a value in my array, it prints out a garbage value then on the next line what I actually want to print. When I enter a value not in the array it errors out. I am new to this so could be something stupid
.data
array: .word 2,3,1,5,6,7,1,4,8,8 #elements
N: .word 10 # 10 elements
key: .word 0
int: .word 9
search:
la $a0, array
la $t0, N
lw $t0, ($t0)
sll $t0, $t0, 2
addi $t0, $t0, -4
add $a1, $a0, $t0
la $a0, array
jal isort #insert function from other function
li $v0, 4
la $a0, enterKey # Display text
syscall
li $v0,5 # read input
syscall
sw $v0, key
syscall
move $t0, $s0
lw $t1, N
lw $t2, ($t0)
li $t3,0 # $t3 i = 0
lw $t4, int
lw $t5, key
lw $t6, int
loopKey:
beq $t3, $t1, endKey # if i = n, loop ends
bne $t2, $t5, condKey # if the elements are not equal
move $t4, $t3 # assign index found to variable
j endKey
condKey:
addi $t3, $t3, 1 # i++
addi $t0, $t0, 4
lw $t2, ($t0)
j loopKey
endKey:
beq $t4, $t6, noKey #does not appear to even work???
li $v0, 4
la $a0, keyFmsg
syscall
li $v0, 1
add $t4, $t4, 1 # have to add 1 for location not index
add $a0, $zero, $t4 # prints the location
syscall
j displayMenu
noKey: #not working idk why
li $v0, 4
la $a0, keyNFmsg
syscall
j displayMenu

Reverse words of a sentence in mips

You are given a string, like "hello what is your name?"
You have to reverse the words, using a recursive function.
So the result of the example string is "name? your is what hello"
The language is MIPS assembly.
Here is what I have done so far: (The code doesn't end unfortunately :| and I can't find the issue)
.macro print_int(%arg)
li $v0, 1
add $a0, %arg, $zero
syscall
.end_macro
.macro print_string(%arg)
move $t9, $a0
li $v0, 4
add $a0, %arg, $zero
syscall
move $a0, $t9
.end_macro
.text
la $s0, string
li $s1, 32 # space
la $t8, space
sub $s0, $s0, 1
sb $s1, 0($s0)
# find the length of the string
move $t0, $s0 # $t0 = i = the iterator
L1: lb $t1, 0($t0) # $t1 = i'th char of the string
beq $t1, 0, Exit # if string[i] == null, Exit
addi $t0, $t0, 1 # i++
j L1
Exit:
sub $s3, $t0, $s0 # $s3 is the length of the string
# Set arguements
move $a0, $s0
move $a1, $t0 # endFlag = length of the string
jal reverse # call the function
li $v0, 10
syscall # exit
reverse:
# save registers
sub $sp, $sp, 12
sw $ra, 0($sp)
sw $a0, 4($sp)
sw $a1, 8($sp)
bgt $a1, $s0, L2 # base case
add $sp, $sp, 12
jr $ra
# find a word in the string
L2:
add $t0, $zero, $a1
add $t3, $a0, $s3 # address of last character of the string
Loop:
lb $t4, 0($t3) # chracter from the string
seq $v0, $s1, $t4 # if space
ble $t3, $a0, Exit_Loop # if first of string
beq $v0, 1, Exit_Loop # if character was space
sub $t3, $t3, 1
j Loop
Exit_Loop:
sb $zero, 0($t3)
add $t3, $t3, 1
print_string($t3)
print_string($t8)
#recursive call
move $a1, $t3
jal reverse
# load registers
lw $ra, 0($sp)
lw $a0, 4($sp)
lw $a1, 8($sp)
add $sp, $sp, 12 # release the stack
jr $ra
.data
string: .asciiz "hello what is your name?"
newline: .asciiz "\n"
space: .asciiz " "
Your code does not stop from entering the function recursive even if the string is empty ($t3 == $a0 + 1).
Here's a quick fix: replace your code:
Exit_Loop:
sb $zero, 0($t3)
add $t3, $t3, 1
print_string($t3)
print_string($t8)
#recursive call
move $a1, $t3
jal reverse
with:
Exit_Loop:
sb $zero, 0($t3)
add $t4, $t3, 1
print_string($t4)
print_string($t8)
ble $t3, $a0, Exit_Func
#recursive call
move $a1, $t4
jal reverse
Exit_Func:
Also, please notice that your macro print_int doesn't store/restore the value of $a0, also even in print_string you store/restore $a0 using $t9, that's still dangerous since according to the MIPS32 ABI the values in register $t[0-9] are not guaranteed to be reserved during a syscall (while in $s[0-7] it is guaranteed).

Checksum assembly algorithm not adding up to correct value

I'm working on implementing a basic checksum algorithm for an inputted string in MIPS assembly as a general introduction to working in the language, and I could use some error checking.
Here's what I have so far, comments included to keep track of what's happening each step:
.data
str1:
.asciiz "This is a short string."
cs1:
.word 0x84a
str2:
.asciiz "This is a much longer string. In fact, it has two sentences in it, and some funny characters (~`)€."
cs2:
.word 0x230a
NonSuccessString:
.asciiz "You have more work to do."
Test1Success:
.asciiz "Test 1 was successful. "
Test2Success:
.asciiz "Test 2 was successful. "
.text
la $a0, str1 #Set $a0 to address of label str1:
jal checksum #Set $ra to address of next instruction, then jump to label checksum:
la $s0, cs1 #Set $s0 to address of label cs1:
lw $s1, 0($s0) #Set $s1 to contents of memory address $s0
beq $v0, $s1, Success1 # If $v0 and $sl are equal, jump to label Success1:
j NonSuccess # Jump to label NonSuccess:
Success1:
la $a0, Test1Success #Set $a0 to address of label Test1Success:
addi $v0, $zero, 4
syscall
la $a0, str2 #Set $a0 to address of label str2:
jal checksum #Set $ra to return address, then jump to label checksum:
la $s0, cs2 #Set $s0 to address of label cs2:
lw $s1, 0($s0) #Set $s1 to contents of memory address $s0
beq $v0, $s1, Success2 # If $v0 and $sl are equal, jump to label Success2:
j NonSuccess # Jump to label NonSuccess:
Success2:
la $a0, Test2Success #Set $a0 to address of label Test2Success:
addi $v0, $zero, 4
syscall
j Quit # Jump to label Quit:
NonSuccess:
la $a0, NonSuccessString #Set $a0 to address of label NonSuccessString:
addi $v0, $zero, 4
syscall
Quit:
addi $v0, $zero, 10
syscall
checksum:
addi $sp, $sp, -4 # adjust stack for 1 item
sw $s0, 0($sp) # save $s0
add $s0, $zero, $zero # i = 0
L1:
add $t1, $s0, $a0 # Locate the character at y[i]
lbu $t2, 0($t1) # Load the unsigned byte value of y[i]
beq $t2, $zero, L2 # exit loop if y[i] == 0
add $v0, $v0, $t2 # Add the byte to the total value
addi $s0, $s0, 1 # i = i + 1
j L1
L2:
jr $ra #jump back to $ra
The simple string in the first test calculates correctly and I get the first "Test 1 was successful." message, but on the second checksum the debug reports a sum of 0x230e, 4 more than the expected value, meaning something wonky happened. I'm guessing the special characters are probably causing the issue, but I don't know for sure. Any ideas?
You're not resetting $v0 prior to calculating the checksum. There should be an add $v0,$zero,$zero before the L1: label.
But I still don't see where the value 0x230a comes from. It seems to me like the correct checksum for the second string is 0x22de.

How to iterate a string in mips assembly

So I am working on a project right now where we have to take in a string and convert it to all uppercase letters and then to lowercase letters if either the toUpper or toLower byte is anything but 0. Right now I am still working on the uppercase portion (guessing the lowercase will be almost the same) but I am getting stuck either when I am going through the string to find the letters that are uppercase or when I am calling the syscall to print. Any help would be great. Here's what I have so far:
.data
toUpper: .byte 1
toLower: .byte 0
string:
.asciiz " A long time ago in a Galaxy far, far away...."
# Your code goes below this line
origString:
.asciiz "Original string:\n"
toUpForwardStr:
.asciiz "\nConverted to upper-case:\nForward:\n"
toLowerForwardStr:
.asciiz "\nConverted to lower-case:\nForward:\n"
backwardStr:
.asciiz "Backward:"
.text
main:
# Function prologue
subu $sp, $sp, 24 # allocate stack space -- default of 24 here
sw $fp, 0($sp) # save caller's frame pointer
sw $ra, 4($sp) # save return address
addiu $fp, $sp, 20 # setup main's frame pointer
la $a0, origString #Print "Original String:"
addi $v0, $zero, 4
syscall
la $a0, string #Print string
addi $v0, $zero, 4
syscall
la $s0, toUpper
sb $s1, 0($s0) #toUpper stored in $s1
la $s0, toLower
sb $s2, 0($s0) #toLower stored in $s2
bne $s1, $zero, toUpperCase #Jump toUpperCase if toUpper ≠ 0
toUpperCase:
la $a0, toUpForwardStr #Print "Converted to upper-case:"
addi $v0, $zero, 4 # "Forward:"
syscall
la $s3, string #$s3 holds address to string
addi $s1, $zero, 0 #$s1 = i = 0
j upperCaseLoop #Goto upperCaseLoop
upperCaseLoop:
# Compute address of string[i]
add $t2, $s3, $s1 # $t2 = address of string[i]
lb $t3, 8($t2) # $t3 = elements[i]
beq $t3, $zero, upperDone # test if for loop is done
addi $t6, $zero, 96 #$t6 = 96 (lowercase letters)
bgt $t3, $t6, isLowercase1#If letter is lowercase goto isLowercase1
comeBackFromLowercaseIfs:
move $t3, $a0
addi $v0, $zero, 11
syscall
addi $s1, $s1, 1 # i++
j upperCaseLoop
upperDone:
bne $s2, $zero, toLowerCase #Jump toLowerCase if toLower ≠ 0
toLowerCase:
la $a0, toLowerForwardStr #Print "Converted to lower-case:"
addi $v0, $zero, 4 # "Forward:"
syscall
j done #The END!!
isLowercase1:
addi $t7, $zero, 123 #$t7 = 123
blt $t3, $t7, isLowercase2 #Goto isLowercase2
j comeBackFromLowercaseIfs #Go back to uppercaseLoop
isLowercase2:
addi $t3, $zero, -30 #changes letter to lowercase
j comeBackFromLowercaseIfs #Go back to uppercaseLoop
done:
# Epilogue for main -- restore stack & frame pointers and return
lw $ra, 4($sp) # get return address from stack
lw $fp, 0($sp) # restore the caller's frame pointer
addiu $sp, $sp, 24 # restore the caller's stack pointer
jr $ra # return to caller's code
1 This
move $t3, $a0
should be
move $a0, $t3
2 This
lb $t3, 8($t2)
should be
lb $t3, 0($t2)
3 This
addi $t3, $zero, -30 #changes letter to lowercase
should be
addi $t3, $t3, -32 #changes letter to lowercase

Complications in MIPS code of Recursive Reversal of a string

I have written this MIPS code of recursive reversal of a string. However, the output is coming out to be the same that has been input by the user. Can someone please help me out and indicate where am I going wrong? Please reply as soon as possible.
# Program to reverse a string input by the user
.data
.align 2
array: .space 50
input: .asciiz "Enter a string: "
output: .asciiz "\nThe reversed string is: "
.text
.globl main
main:
addi $s0, $zero, 50
addi $t0, $zero, 0
la $a0, input
li $v0, 4
syscall
la $a0, array
li $v0, 8
syscall
initiate:
add $t0, $a0, $zero # initial address
add $t1, $zero, $zero # count=0
add $t2, $zero, $zero # i=0
la $t0, array # base address of the array
add $t3, $t0, $t2 # & array[i]
loop:
lb $t3, 0($t3) # fetch array[i]
beqz $t3, EndOfString # loop exits if it is a null character;array[i] !='\0'
bne $t3, $0, continue # otherwise loop continues
add $t1, $t1, 1 # count++
continue:
add $t2, $t2, 1 # i++
j loop
addi $a1, $zero, 50
jal StringReversal
EndOfString:
la $a0, output
li $v0, 4
syscall
la $a0, array
li $v0, 4
syscall
li $v0, 10
syscall
StringReversal:
add $t0, $a0, $zero # initial address
add $t4, $zero, $zero # j = start = 0
addi $t5, $a1, -1 # k = end-1
SwapLoop:
add $t6, $t0, $t4
lb $t7, 0($t6) # load byte array[start]
add $t8, $t0, $t5
lb $t9, 0($t8) # load byte array[end-1]
sb $t7, 0($t8) # array[end-1] = array[start]
sb $t9, 0($t6) # array[start] = array[end-1]
addi $t4, $t4, 1 # j++
addi $t5, $t5, -1 # k--
slt $t9, $t5, $t4
beqz $t9, SwapLoop
jr $ra
# Program to reverse a string input by the user
.data
.align 2
array: .space 50
input: .asciiz "Enter a string: "
output: .space 50
size: .word 49
.text
j main
length:
# return length of the input string
# $a0 - address of string
# $v0 - length of the string
move $v0, $zero # set $v0 to 0
length_loop:
lb $t0, 0($a0)
beqz $t0, length_end
addi $v0, $v0, 1
addi $a0, $a0, 1
b length_loop
length_end:
subi $v0, $v0, 1
jr $ra
reverse:
# $a0 - address of string to reverse
# a1 - length of the string
# a2 - address of string where to store the reverse
addi $sp, $sp, -4
sw $ra, 0($sp)
bltz $a1, reverse_end
lb $t0, 0($a0)
subi $a1, $a1, 1
subi $a0, $a0, 1
sb $t0, 0($a2)
addi $a2, $a2, 1
jal reverse
reverse_end:
lw $ra, 0($sp)
addi $sp, $sp, 4
jr $ra
main:
addi $s0, $zero, 50
addi $t0, $zero, 0
la $a0, input
li $v0, 4
syscall
# read string from the user into $a0
la $a0, array
lw $a1, size
li $v0, 8
syscall
# reverse the string
jal length # $v0 contains length of string
la $a0, array
move $a1, $v0
add $a0, $a0, $a1 # pointer to the last character
la $a2, output
jal reverse
# print the reverse string
la $a0, output
li $v0, 4
syscall
Output:
Enter a string: hello
olleh
-- program is finished running (dropped off bottom) --
In your continue label, it looks as though j loop is called too early, and hence
addi $a1, $zero, 50
jal StringReversal
is never reached, hence the instructions in the StringReversal label are not performed.

Resources