MIPS - Printing a certain number of characters from a string - mips

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

Related

How to i fix my error when trying to calculate the sum using mips?

goodday, so currently my code prompts the user to enter a sum. my program then takes these stored values and outputs the sum of them. However, currently my code is not outputting the correct total and i am unsure where the problem lies.
i have attached my code below:
.text
main:
#Prompt
la $a0, prompt
li $v0, 4
syscall
# Get input string
li $v0, 8
la $a0, string_input
li $a1, 1024
move $t0, $a0
syscall
# initialise sum
lb $t2, ($t0) # Initialise the sum as the first value
addi $t2, $t2, -48 # Convert to decimal value
addu $t0, $t0, 1
b loop
loop:
lb $t3, ($t0) # Store the sign
lb $t1, 1($t0) # Store the value
addu $t0, $t0, 2 # increment the counter
beq $t1, 10, end_loop # If reached the end of the string
# Manipulate sign value to 1 if '+'
add $t3, $t3, 4
add $t2, $t2, $t1 # Add the value to the sum
b loop # re-iterate
end_loop:
# Printing the total sum
move $a0, $t2
li $v0, 1
syscall
# Exiting program
li $v0, 10
syscall
.data
string_input: .space 1024
prompt: .asciiz "Enter a sum:\n"
the current output should be 11 but this is what is outputted instead:
Enter a sum:
2+3+6
727

Printing an hourglass in mips32

I'm having problems solving this question. I want to print an hourglass using mips32. n is an integer given by user as input and the hourglass must be printed in n lines. For example, for n = 5 the output is:
*****
***
*
***
*****
Here is my code for the first part (the triangle top of the hourglass). The problem is that it prints only the first line of stars and then exits. By running my code line by line in Mars, I understood that the first line of the backToLoop1 label is run every time loop3 is run! So it causes the program to end after the first line. I really can't realize why this happens.
.data
newLine: .asciiz "\n"
.text
main:
li $v0, 5 # read n
syscall # call sysetem
addi $t2, $v0, 0 # moves n to $t2
li $t0, 1 # i= 1
loop1:
blt $t2, $t0, Exit # if n<i exit
la $a0, newLine # go to next line
addi $v0, $0, 4 # 4 represents printing string
syscall # call system
# loop2 bounds
li $t1, 1 # k= 1
subi $t3, $t0, 1 # $t3= i-1 upper bound for loop2
# loop3 bounds
li $t5, 1 # j= 1
addi $t6, $t2, 1 # t6= n+1
sub $t6, $t6, $t0 # $t6= n+1-i upper bound for loop3
loop2:
blt $t3, $t1, loop3
li $a0, ' ' # load space to $a0
la $v0, 11 # 11 represents printing character
syscall # call system
addi $t1, $t1, 1 # k++
ble $t1, $t3, loop2 # if <= i-1 loop2 again
loop3:
blt $t6, $t5, backToLoop1 # back to loop1
li $a0, '*' # load star to $a0
la $v0, 11 # 4 represents printing character
syscall # call system
addi $t5, $t5, 1 # j++
ble $t5, $t6, loop3 # if j <= n-i+1 loop3 again
backToLoop1:
addi $t0, $t0, 1 # i++
ble $t0, $t2, loop1 # if i<=n loop1 again
blt $t2, $t0, Exit
Exit: # Terminate the program
li $v0, 10 # 10 represents exit
syscall # call system
You're off to a good start. However, there doesn't appear to be a clear strategy for slanting the right side of the hourglass. Ideally we can write logic to handle drawing the bottom half without duplicating most of the logic.
My default approach for this sort of pattern is to use two pointers, a left starting at 0 and right starting at n - 1. These represent the index bounds for the asterisk characters for each row. Per row iteration, decrement the right pointer and increment the left pointer, essentially drawing an "X" pattern on the n by n grid.
This strategy gets us 95% of the way there. The last step is to temporarily swap the left and right pointers if left > right, which handles drawing the bottom half without too much spaghetti.
.data
prompt: .asciiz "enter a number: "
.text
main:
la $a0 prompt # collect n
li $v0 4
syscall
li $v0 5
syscall
move $s3 $v0 # n
li $s0 0 # left index
move $s1 $s3 # right index = n - 1
addi $s1 $s1 -1
row_loop:
bltz $s1 exit # while right-- >= 0
li $s2 0 # column index
col_loop:
beq $s2 $s3 row_loop_done # for 0..n
# if left > right, swap temporarily
move $t0 $s0
move $t1 $s1
blt $t0 $t1 pick_char
move $t2 $t0
move $t0 $t1
move $t1 $t2
pick_char:
# '*' if left <= i <= right else ' '
blt $s2 $t0 pick_space
bgt $s2 $t1 pick_space
li $a0 42 # print '*'
j print_char
pick_space:
li $a0 32 # print ' '
print_char:
li $v0 11
syscall
addi $s2 $s2 1 # column index++
j col_loop
row_loop_done:
li $a0 10 # print newline
li $v0 11
syscall
addi $s1 $s1 -1 # right--
addi $s0 $s0 1 # left++
j row_loop
exit:
li $v0 10
syscall

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 prompt for a string and exchange the case of each character

I am writing a MIPS program that prompts the user for a string and then parse the string exchanging the case of each character.
for example ->
Hey You becomes hEY yOU.
My question is, how do i make it do nothing if it encounters a space ? Any help would be great!
.data
string4:.space 82 # space for input string
strPrompt:.asciiz "Please enter a string: "
.text
.globl main
main:
la $a0, strPrompt # print prompt
li $v0, 4
syscall
la $a0, string4 # read string
li $a1, 80
li $v0, 8
syscall
la $a0, string4 # print string
li $v0, 4
syscall
la $t0, string4 # $t0 = &string4[0]
li $t1, 0
loop4:
lb $t1, 0($t0)
nop
nop
beqz $t1, done4 # if $t1 == NUL, we are done
bgt $t1, 90, else # if char > 90 its a lower case
nop
addi $t1, $t1, 0x20 # if < 90 its upper case add 32
sb $t1, 0($t0)
addi $t0, $t0, 1 # add 1 to pointer
j loop4 # jump back to loop
nop
else:
addi $t1, $t1, -0x20
sb $t1, 0($t0)
addi $t0, $t0, 1
j loop4
nop
done4:
Here's a branchless way of changing the case of a character in $t1 if it's in the range A..Z or a..z, and do nothing if it's outside that range:
# if (upper($t1) >= 'A' && upper($t1) <= 'Z') $t2 = 1; else $t2 = 0;
andi $t3,$t1,0xDF # clear bit 5, if $t1 was an alphabetic character $t3 will now be uppercase
li $t2,'A'-1
sltu $t2,$t2,$t3
sltiu $t3,$t3,'Z'+1
and $t2,$t2,$t3
sll $t2,$t2,5 # $t2 = 0x20, or 0
xor $t1,$t1,$t2 # either swap case or do nothing