Mips blank space on address - ascii

So I have a string of chars. I need to check if a character is blank space " "/ ascii 32. How can I give an address ascii value of blank space so I can use it in if/else?
.data
userInput: .space 40
.text
main:
li $v0, 8
la $a0, userInput
li $a1, 40
syscall
li $t1,0
la $t0,userInput
loop:
li $a3, 32 #can i give this address 32 ascii value?
lb $a0,0($t0)
beqz $a0,done
addi $t0,$t0,1 #going true the characters
bne $t0, $a3, L1 # branch if ! ( char == ' ' )
addi $t1,$t1,1 #add blank space
L1: addi $t2,$t2,1 #add characters
j loop
done:
li $v0,1
addi $t1, $t1, -1
add $a0, $0,$t1
syscall
li $a0, 32
li $v0, 11
syscall
li $v0,1
addi $t2, $t2, -1
add $a0, $0,$t2
syscall
li $v0,10
syscall

.data
blankSpace: .ascii " "
.text
main:
la $a3, blankspace
lb $t3,0($a3)
Alternative you can directly load the ASCII value for space which is 0x20 in ASCII table.
li $a3, 0x20

Related

Runtime exception at 0x0040002c: address out of range 0x00000001 in MIPS Assembler for ceasar encryption

The Programm compiles just fine but as soon as i give input this error is thrown:
"Error in line 28: Runtime exception at 0x0040002c: address out of range 0x00000001
Processing terminated due to errors."
Here ist the code for my programm:
.data
line: .space 80
.text
main:
# read line from stdin
li $v0, 8
la $a0, line
li $a1, 80
syscall
# call caesar_line
li $a0, 1
jal caesar_line
# return 0
li $v0, 0
jr $ra
caesar_line:
# save start of line
move $t0, $a0
# loop through line
loop:
# load the character from memory
move $t1, $a0
lb $a0, 0($t1)
beqz $a0, end_loop
jal caesar_char
sb $v0, 0($t1)
addi $t1, $t1, 1
move $a0, $t1
j loop
end_loop:
# print line
li $v0, 4
move $a0, $t0
syscall
jr $ra
caesar_char:
# check if c is lowercase
blt $a0, 'a', upper
bgt $a0, 'z', not_alpha
addi $a1, $a1, 'a'
jal caesar_helper
j done
upper:
# check if c is uppercase
blt $a0, 'A', not_alpha
bgt $a0, 'Z', not_alpha
addi $a1, $a1, 'A'
jal caesar_helper
j done
not_alpha:
# not an alphabetical character
move $v0, $a0
j done
caesar_helper:
# subtract base from c
sub $t0, $a0, $a2 # $t0 = c - base
# add distance + 26 to c
addi $t0, $t0, 26 # $t0 += 26
add $t0, $t0, $a1 # $t0 += distance
# calculate c % 26
li $t1, 26 # $t1 = 26
div $t0, $t1 , $t1 # $lo = c % 26
mflo $t0
# add base to c
add $v0, $t0, $a2 # $v0 = c + base
done:
jr $ra
Not even ChatGBT could find an error.
The code should shift all chars of an string by a certain amount, but as soon as it is run the error above is thrown.

MIPS find end of string

I have the following mips code (running it in QTSPIM), that is supposed to count the number of characters in a string and print them.
The logic behind it is very simple but is does not work as it should. Everything goes well until it reaches the end of the string and then it continues counting even though I compare each element to $zero to find the end of string (\0).
Is there something wrong with my condition to exit the loop, or my_string does not contain \0 in the end so it won't exit?
.data
endl: .asciiz "\n"
my_string: .asciiz "thisisastring"
star: .asciiz "*"
str_end: .word 0
space: .asciiz " "
.text
.globl main
main:
la $a0, my_string
li $v0, 4
syscall
la $a0, endl
li $v0, 4
syscall
la $t0, my_string # load mystring to $t0
li $t1, 0 # make $t1 = 0, character counter
lb $t2, ($t0) # make $t2 point to the first character of "my_string"
li $t3, 1 # $t3 is the ++ register to go to the next character
li $t4, 0 # character counter
la $t5, str_end
cont:
beqz $t0, print # if \0 is found print and exit
addi $t4, $t4, 1 # increase the counter
lbu $a0, ($t0) # print current character
li $v0, 11
syscall
addi $t0, $t0, 1 # go to next char
#move $t2, $t0
j cont
print:
move $a0, $t4
li $v0, 1
syscall
j exit
exit:
li $v0, 10
syscall
The problem is in the order of the instructions, the logic of the code.
Here is the corrected version with no redundant code:
.data
endl: .asciiz "\n"
my_string: .asciiz "thisisastring"
str_end: .word 0
.text
.globl main
main:
la $a0, my_string
li $v0, 4 # print the string
syscall
la $a0, endl # print endl
li $v0, 4
syscall
la $t0, my_string # load mystring to $t0
li $t1, 0 # make $t1 = 0, character counter
lb $t2, 0($t0) # make $t2 point to the first character of "my_string"
la $t5, str_end
cont:
lb $a0, 0($t0) # print current character
beqz $a0, print # if \0 is found print and exit
addi $t1, $t1, 1 # increase the counter
addi $t0, $t0, 1 # go to next char
li $v0, 11
syscall
j cont
print:
move $a0, $t1
li $v0, 1
syscall
j exit
exit:
li $v0, 10
syscall

Sorting program with MIPS

I have some problem when I'm writing a sorting program in MIPS.
The function of this program is like this: Input 10 integers from keyboard and print them out, then sort them and print the sorted array again.
But the output is different from what I expect, some numbers are not sorted, would someone help me?
.data
str1: .asciiz "Please input integer numbers, maximum 10: \n"
str2: .asciiz "The 10 integer numbers you input are: \n"
str3: .asciiz "The numbers you entered are sorted as: \n"
array: .space 40
space: .asciiz " "
.text
.globl main
main:
la $t6, array #load the address of array into $t6
move $t7, $t6
addi $t7, $t7, 40 #point $t7 to the end of the array
jal readin
la $t6, array
la $a0, str2
li $v0, 4
syscall
jal print1 #print out the array before sort
la $t0, array #put the address of array into $t0
add $t0, $t0, 40 #put $t0 to the end of the array
move $t1, $zero #set $t1 as counter of the outerloop
li $t2, 10 #set $t2 as number of the outerloop
la $t3, array #put the address to $t3
jal innerloop
la $a0, str3
li $v0, 4
syscall
la $t3, array
#move $t7, $t3
#add $t7, $t7, 40
jal print2
li $v0, 10
syscall
innerloop:
lb $t4, 0($t3)
lb $t5, 4($t3)
bgt $t4, $t5, swap
addi $t3, $t3, 4
blt $t3, $t0, innerloop #if $t3 < $t0, keep in the innerloop to check two #neighbor numbers
jal outerloop #jump to outerloop if one round is finished
swap:
sb $t4, 4($t3)
sb $t5, 0($t3)
addi $t3, $t3, 4
#sll $t3, $t3, 2
blt $t3, $t0, innerloop #
jr $ra
outerloop:
la $t3, array
addi $t1, $t1, 1 #add the outerloop counter $t1 by one,
addi $t0, $t0, -1
blt $t1, $t2, innerloop #if $t1 < $t2, keep searching
jr $ra
readin:
la $a0, str1 #print str1
li $v0, 4
syscall
li $v0, 5 #read in the number
syscall
sb $v0, ($t6) #store the number in the array
add $t6, $t6, 4
blt $t6, $t7, readin
jr $ra
print1:
lb $a0, ($t6)
li $v0, 1
syscall
li $a0, 32
li $v0, 11 # syscall number for printing character
syscall
add $t6, $t6, 4
blt $t6, $t7, print1
jr $ra
print2:
lb $a0, ($t3)
li $v0, 1
syscall
li $a0, 32
li $v0, 11 # syscall number for printing character
syscall
add $t3, $t3, 4
blt $t3, $t0, print2
jr $ra
And the result in SPIM is like this:
Please input integer numbers, maximum 10:
44
Please input integer numbers, maximum 10:
11
Please input integer numbers, maximum 10:
33
Please input integer numbers, maximum 10:
22
Please input integer numbers, maximum 10:
66
Please input integer numbers, maximum 10:
55
Please input integer numbers, maximum 10:
99
Please input integer numbers, maximum 10:
77
Please input integer numbers, maximum 10:
88
Please input integer numbers, maximum 10:
24
The 10 integer numbers you input are:
44 11 33 22 66 55 99 77 88 24 The numbers you entered are sorted as:
11 33 22 44 55 66 77 88 24 32
Would someone please explain to me why there is a 32 in the end and why they are not sorted properly?

Case sorting in mips

I have a program that will capitalize all lowercase letters and lowercase all the uppercase letters entered in a string by the user. It does this by adding or subtracting 32 from the character value to get the desired character. My problem is that it doesn't change anything in the string. Any suggestions on what to change?
.data
prompt: .asciiz "\n\nEnter an string of characters: "
result: .asciiz "\n\nHere is the string you entered: "
after_sort: .asciiz "\n\nHere is the string after the case sorting: "
buffer: .space 80
.text
main:
#Prints the prompt string
li $v0, 4
la $a0, prompt
syscall
#reads string from user and saves in $a0
li $v0, 8
la $a0, buffer
li $a1, 80
syscall
#Prints the result string
li $v0, 4
la $a0, result
syscall
#Prints the string entered by the user
la $a0, buffer
li $v0, 4
syscall
li $t0, 0 # t0 = i = 0
for_loop:
slti $t1, $t0, 80 # t1 = 1 if and only if t0 < 80
beq $t1, $0, for_loop_done
slti $t2, $a0, 91
li $t3, 1
beq $t2, $t3, upper #if the character value is less than 91 branch to upper addition
bne $t2, $t3, lower
upper:
addi $a0, $a0, 32 #adds 32 to the character value to lowercase it
lower:
subi $a0, $a0, 32 #subtracts 32 from the character value to capitalize it
addi $t0, $t0, 1
j for_loop
for_loop_done:
#Prints the result string
li $v0, 4
la $a0, after_sort
syscall
#Prints the string entered by the user
la $a0, buffer
li $v0, 4
syscall
exitProgram: li $v0, 10 # system call to
syscall # terminate program
You are using $a0as a character, such as here:
slti $t2, $a0, 91
but it is never filled with the character. At the moment, it contains a memory address, not a character.
You should load the character using lb and store it back after making it upper/lowercase using sb.
Feel free to add a comment if you want a code example.
Edit: the changes in the relevant part of the code:
...
li $t0, 0 # t0 = i = 0
for_loop:
slti $t1, $t0, 80 # t1 = 1 if and only if t0 < 80
beq $t1, $0, for_loop_done
lb $t4, 0($a0)
beqz $t4, for_loop_done
beq $t4, 10, for_loop_done
slti $t2, $t4, 91
li $t3, 1
beq $t2, $t3, upper #if the character value is less than 91 branch to upper addition
bne $t2, $t3, lower
upper:
addi $t4, $t4, 32 #adds 32 to the character value to lowercase it
j done
lower:
addi $t4, $t4, -32 #subtracts 32 from the character value to capitalize it
done:
addi $t0, $t0, 1
sb $t4, 0($a0)
addi $a0, $a0, 1
j for_loop
for_loop_done:
#Prints the result string
...
It's easy to forget that in assembly, you can't do this:
if something
do this
else
do that
There is no "else", only shudder Goto.
So in this code:
slti $t2, $a0, 91
li $t3, 1
beq $t2, $t3, upper #if the character value is less than 91 branch to upper addition
bne $t2, $t3, lower
upper:
addi $a0, $a0, 32 #adds 32 to the character value to lowercase it
lower:
subi $a0, $a0, 32 #subtracts 32 from the character value to capitalize it
addi $t0, $t0, 1
When you branch to upper, it adds 32. Then it subtracts 32, because execution progressed to the next line. So your code capitalizes lower case, but does nothing to uppercase.
You need to add a jump to the first instruction after your if/then/else equivalent:
upper:
addi $a0, $a0, 32 #adds 32 to the character value to lowercase it
j done # No, I don't want to subtract it again!
lower:
subi $a0, $a0, 32 #subtracts 32 from the character value to capitalize it
done:
addi $t0, $t0, 1
In fact, you should probably get rid of the bne altogether - it's redundant. If beq doesn't branch, then it's not equal. So this would be the finished product:
slti $t2, $a0, 91
li $t3, 1
beq $t2, $t3, upper #if the character value is less than 91 branch to upper addition
# Otherwise, it's lower
subi $a0, $a0, 32 #subtracts 32 from the character value to capitalize it
j done
upper:
addi $a0, $a0, 32 #adds 32 to the character value to lowercase it
done:
addi $t0, $t0, 1
Hope that helps!
(Edit: #Patrik is right too, you need to "dereference" $a0. My example doesn't take that into account.)
here is my code:
it works perfectly
.data
theString:
.space 20
prompt: .asciiz "Enter a string of characters: "
.text
main:
li $v0, 4
la $a0, prompt
syscall
li $v0, 8
la $a0, theString
li $a1, 20
syscall
li $v0, 4
syscall
la $t1,theString
for: lb $a0, 0($t1)
beqz $a0,out #to find out end of string
beq $a0,10,out #to find out end of string
slti $t2, $a0,91 #if $a0<91 $t2=1
beq $t2,1,small
beq $t2,0,capital
capital:
subu $a0, $a0, 32
li $v0,11
syscall
addi $t1,$t1,1
j for
small:
addi $a0, $a0, 32
li $v0,11
syscall
addi $t1,$t1,1
j for
out:
li $v0, 10
syscall

Load byte on mips32

I'm starting with mips32 and I'm getting stuck when trying to get a letter from a string to print it. The code should get the string, print it character by character and when it finds an i print iiing.
.data
msg: .asciiz "testing"
i: .asciiz "iiing"
.text
.globl main
main:
la $t0, msg
la $t1, i
li $t2, 0
loop:
bneq $t0, 105, end #$t0=i?
lb $a0, ($t0)
li $v0, 4
syscall
addi $t0, $t0, 1
b loop
end:
move $a0, $t1
li $v0, 4
syscall
Where is the problem?
You have a few problems.
You are comparing $t0, which is the address of the current character, not the character itself. Move that test below the lb line and test against $a0.
105 in ASCII is E, not i. Try 151 (or to be more normal, 0x69).
You want to compare with beq, not bneq.
Inside the loop, you should use syscall 11, which prints a single character, rather than the current syscall 4 you're using, which prints a string.
Your program doesn't make an exit syscall (10) at the end.
You can look at this link for a list of syscalls.
Here's a complete working program for reference:
.data
msg: .asciiz "testing"
i: .asciiz "iiing"
.text
.globl main
main:
la $t0, msg
la $t1, i
li $t2, 0
loop:
lb $a0, ($t0)
beq $a0, 0x69, end
li $v0, 11
syscall
addi $t0, $t0, 1
b loop
end:
move $a0, $t1
li $v0, 4
syscall
li $v0, 10
syscall

Resources