MIPS assembly - removing vowels from an input string - string

The following is my code for a MIPS assembly program that is intended to remove vowels from an input string and then print the new string. As it stands, the program simply does not remove the vowels and just reprints the same string that was input.
.text
.globl main
main:
# display prompt
li $v0, 4
la $a0, prompt
syscall
# accept input string
li $v0, 8
la $a0, str
li $a1, 82
syscall
li $t0, 0 # add a null to the bottom of the stack
subu $sp, $sp, 4
sw $t0, ($sp)
li $t1, 0 # initiate index
pushloop:
lbu $t0, str($t1) # (I think the program is placing a zero in $t0 here, thus causing it to branch immediately to poploop, which then branches to the end since only the null has been pushed onto the stack)
beqz $t0, poploop # once we reach null char, finish
subu $sp, $sp, 4
sw $t0, ($sp)
addiu $t1, $t1, 1
j pushloop
nop
# $t1 is not reset
poploop:
lw $t0, ($sp)
addu $sp, $sp, 4
beqz $t0, done # once we reach null char, finish
nop
# check if vowel
li $t2, 0x61 # a
beq $t0, $t2, vowel
nop
li $t2, 0x65 # e
beq $t0, $t2, vowel
nop
li $t2, 0x69 # i
beq $t0, $t2, vowel
nop
li $t2, 0x6F # o
beq $t0, $t2, vowel
nop
li $t2, 0x75 # u
beq $t0, $t2, vowel
nop
# if not a vowel, store it at current index in string
sb $t0, str($t1)
j decrement
nop
vowel: # if vowel, remove character
li $t0, 0
sb $t0, str($t1)
decrement:
addiu $t1, $t1, -1 # decrement index
j poploop
nop
done:
li $v0, 4
la $a0, str
syscall
li $v0, 10 # exit program
syscall
nop
.data
str: .space 82
prompt: .asciiz "Input a string:\n"

So. I took a look at what you've writen and I've fixed it.
My first thought is I don't know what you are doing with the stack and stack pointer ($sp). It didn't seem necessary so I took it out.
Next is that the approach is wrong. Your approach is to search the string and replace every lower-case vowel (or at least 'a', 'e', 'i', 'o' and 'u') with a 0. This will not work.
If you think about a typical C string, they are delimeted by a 0, so if you take the string My name is Jeoff and apply your algorithm you will get My n\0m\0 \0s J\0\0ff which of course will print as My n.
So instead, I chose a separate algthm that chooses to not store anything in the case of a vowel and instead shift all following characters over by 1. In so doing we can easily remove all vowels from a string without requiring a secondary buffer.
Take a look below:
.text
.globl main
main:
# display prompt
li $v0, 4
la $a0, prompt
syscall
# accept input string
li $v0, 8
la $a0, str
li $a1, 82
syscall
li $t1, 0 # initiate index
li $t3, 0 # vowel count
poploop:
lb $t0 str($t1)
# check if vowel
li $t2, 'a' # a
beq $t0, $t2, vowel
nop
li $t2, 'e' # e
beq $t0, $t2, vowel
nop
li $t2, 'i' # i
beq $t0, $t2, vowel
nop
li $t2, 'o' # o
beq $t0, $t2, vowel
nop
li $t2, 'u' # u
beq $t0, $t2, vowel
nop
# if not a vowel, store it at current index in string less vowel count
sub $t2, $t1, $t3
sb $t0, str($t2)
j next
nop
vowel: # if vowel, inc count
addi $t3, $t3, 1
next:
addi $t1, $t1, 1
beqz $t0, done # once we reach null char, finish
nop
j poploop
nop
done:
li $v0, 4
la $a0, str
syscall
li $v0, 10 # exit program
syscall
nop
.data
str: .space 82
prompt: .asciiz "Input a string:\n"

Related

Removing extra spaces after i enter a string

Hi i was wondering if there was a simple way to remove the spaces i allocated for a string to be entered, or perhaps a way to not compare the empty space after the word. This program is a palindrome detector. Any suggestions would be great.
Ex. output:
racecar, not a palindrome because it has a few empty spaces.
aaaaaaaaaa is a palindrome because it has no empty spaces...
again just need a hotfix to remove the spaces after the word is inputted, or a way to ignore the spaces after the word. Thank You.
.data
intro : .asciiz "Lets See If Your Word is a Palinfrome!\n"
question: .asciiz "Please Enter up to a 10 Character word: "
Y_P: .asciiz "Yes it is!"
N_P: .asciiz "No Its Not!"
str1: .space 10
.text
.globl main
main:
li $v0, 4
la $a0, intro
syscall
li $v0, 4
la $a0, question
syscall
li $v0, 8
la $a0,str1
addi $a1,$zero,10
syscall
move $t0, $a0
palindrome:
addi $t0, $0, 0 # j = 0
length: add $t2, $a0, $t0 # $t2 = &array[j]
lb $t2, 0($t2) # $t2 = array[j]
beq $t2, $0, done # end of string?
addi $t0, $t0, 1 # j = j+1
j length
done: addi $t0, $t0, -1 # j = j-1
addi $t1, $0, 0 # i = 0
loop: slt $t2, $t1, $t0 # $t2 = 1 if i < j
beq $t2, $0, yes # if !(i < j) return
add $t2, $a0, $t1 # $t2 = &array[i]
lb $t2, 0($t2) # $t2 = array[i]
add $t3, $a0, $t0 # $t3 = &array[j]
lb $t3, 0($t3) # $t3 = array[j]
bne $t2, $t3, no # is palindrome?
addi $t0, $t0, -1 # j = j-1
addi $t1, $t1, 1 # i = i+1
j loop
yes: # yes a palindrome
addi $v0, $0, 1
li $v0, 4
la $a0, Y_P
syscall
li $v0, 10
syscall
j yes
jr $ra
no: # not a palindrome
addi $v0, $0, 0
li $v0, 4
la $a0, N_P
syscall
li $v0, 10
syscall
j no
jr $ra

Changing Characters in a String in MIPS (Caesar Shift)

Hey guys i want to write a simple Caesar Shift in MIPS. My program takes in the string to be encrypted/decrypted. Then the program asks for the key (the number of letters to shift) and then asks to encode or decode.
---EDIT ---
Sorry i forgot to clarify my question. The output of my program is "estuvwL" for a shift of 1 on the string "abcde". Obviously, this is not correct. Any thoughts on where i am going wrong?
Here is my code:
.data # Data declaration section
prompt: .asciiz "Enter a message: " #prompt to enter message
key_prompt: .asciiz "Enter a key for this message: " # enter number to shift letters
enc_dec: .asciiz "(e)ncrypt or (d)ecrypt? " # encrypt or decrypt prompt
encode_bytes: .byte 1 #bytes for encoding
key: .word 0 # the variable for encoding key
String: .space 255 # the string to be encrypted/decrypted
encode: .space 1 #the character (e) or (d) to ask encrypt or decrypt
e: .ascii "e"
d: .ascii "d"
.text
main: # Start of code section
__Start:
li $v0, 4 #print string
la $a0, prompt # print the first prompt
syscall
li $v0, 8 # read in string to be encrpyted
la $a0, String # stores string in variable
li $a1, 255 # the string allocates room for up to 255 chars
syscall
li $v0, 4 #print string
la $a0, key_prompt
syscall
li $v0, 5 #code to read in int
syscall # reading in the integer
move $t5, $a0 #moving key to $t5
li $v0, 4 #print string
la $a0, enc_dec #print the encode string
syscall
li $v0, 12 #read character code
#la $a0, encode #load address of encode to register $a0
#li $a1, 2 #limit input to 1 char
syscall
li $s7, 101
li $s6, 100
beq $v0, $s7, __encrypt_Loop
beq $v0, $s6, __decrypt_Loop
__encrypt_Loop:
la $t0, String #holding address of String
__encode_Loop:
lb $t2, ($t0) #loading the byte to be manipulated into $t2
beqz $t2, __print_String # if string is equal to zero, jump to print new string
__continue:
add $t2, $t2, $t5 #adding the key to the string (manipulating chars)
li $t3, 'z' #loading the value of z, for checking purposes
bgt $t3, $t2, __encrypt_Check #if the char is "bigger" than z jump to fix
sb $t2, ($t0) #store the value
addi $t0, 1 #incrementing to next char
j __encode_Loop
__encrypt_Check:
li $s4, 25
sub $t2, $t2, $s4
sb $t2, ($t0) #store char in string
addi $t0, 1 #incrementing to next char
j __continue
__decrypt_Loop:
la $t0, String #holding address of String
# la $t5, key #loading the key into $t5
__decode_Loop:
lb $t2, ($t0) #making $t2 the address of the string
beqz $t2, __print_String # if string is equal to zero, jump to print new string
___continue:
sub $t2, $t2, $t5 #subtracting the key to the string (manipulating chars)
li $t3, 'a' #loading the value of z, for checking purposes
blt $t3, $t2, __decode_Check #if the char is "smaller" than a jump to fix
sb $t2, ($t0) #store the value
addi $t0, 1 #incfementing to next char
j __decode_Loop
__decode_Check:
li $s4, 25
add $t2, $t2, $s4
sb $t2, ($t0) #store char in string
addi $t0, 1 #incrementing to next char
j __continue
__print_String:
li $v0, 4
#move $a0, $t0
la $a0, String
syscall
__end_program:
li $v0, 10
syscall
A few problems here:
First is the line move $t5, $a0 #moving key to $t5 which should read move $t5, $v0 as the syscall returns the key in $v0 not $a0.
Secondly, I'm not sure what the purpose of the "check" functions is, so I commented out the branch to them and everything worked as I expected.
At any rate, the check for them is clearly wrong. You wrote:
blt $t3, $t2, __decode_Check #if the char is "smaller" than a jump to fix
But the arguments are reversed from the comment. It should read
blt $t2, $t3, __decode_Check #if the char is "smaller" than a jump to fix
Likewise for the __encrypt_Check function.

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

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