saving a value inside a mips loop - loops

I've just started to learn MIPS, and as part of our assignment, I'm trying to save a counter value that runs inside a loop.
So, I was able to exit the loop, thanks to Michael. But now the counter will not increase, I noticed that it won't enter the incount label.
.text
.globl main
main:
# get string from user
la $a0, str1 # load the addr of the given string into $a0.
li $v0, 4 # 4 is the print_string syscall.
syscall # do the syscall.
li $v0, 8 # take in input
la $a0, buffer # load byte space into addr
li $a1, 10 # allot the byte space for the string
move $t0, $a0 # save the string into $to
syscall
# get char from user
la $a0, char1 # load the addr of the given char into $a0.
li $v0, 4 # 4 is the print_string syscall.
syscall # do the syscall.
li $v0, 8 # take in input
la $a0, buffer # load byte space into addr
li $a1, 10 # allot the byte space for the char
move $t1, $a0 # save the char into $t1
syscall
addi $s2, $zero,0 # s2 holds the counter
loop:
lb $t3, ($t0)
beq $t3, $t1, incount # go to incount if char was found
beqz $t3, exit # go to exit if we arrived to the end of the string
addi $t0, $t0, 1 # incrase t3 by 1
j loop # go to loop
incount:
addi $s2, $s2, 1 # increase the counter by 1
addi $t0, $t0, 1 # incrase char pos by 1
j loop # go back to loop
exit:
la $a0, ($s2) # counter to be printed
li $v0, 1 # 1 is the print_int syscall.
syscall
li $v0, 10 # return control to SPIM OS
syscall
.data
buffer: .space 10
str1: .asciiz "Please enter your string: "
char1: .asciiz "Now, please enter your char of choice: "
# end countchar.s
Thanks in advance

You've placed your exit routine in the .data section, which is why you're getting the "invalid program counter value" error message. All code needs to be in the .text section.

Related

Exception occurred at PC=0x004000a8 -> (Abort after) -> Followed by Unaligned address in inst/data fetch: 0x1001012b

I am attempting to recreate a C-snippet in assembly. The C program essentially:
creates a char array[256] along with a pointer *A initialized to NULL.
User input of some string is then stored into the char array
while each ith element of the array != 0
check it the ith element is == some DEFINED char value V.
If array[i] == V -> set A = &array[i]
break
Lastly check if A is still initialized to NULL
if not pint address and value of A
else not found
Unfortunately, when I run the MIPS code with Qtspim I get the aforementioned error Exception occurred at PC=0x004000a8
-> (Abort after)
-> Followed by Unaligned address in inst/data fetch: 0x1001012b
I feel like it has something to do with the way that I store my byte values in the array or the way I am accessing those memory locations but I can't figure out what the problem is. Any insight that anyone can offer would be greatly appreciated. Happy holidays everyone!
Bellow is my assembly code:
# global functions aforementioned error
.globl main
# .text assembler directive
.text
# main
main:
# register map
# use $t0 for i
# use $t1 for NULL
# use $s0 for &inputArray[i]
# use $s1 for indexed array value
# use $s2 for the base address inputArray
# use $s3 for result
# use $t2 for constCharlwr
# Prompt user for input
la $a0, str1
li $v0, 4
syscall
# Get user input and store in input array
la $a0, inputArray
li $a1, 256
li $v0, 8
syscall
# set up registers
lb $t0, i
lb $t1, NULL
la $s2, inputArray
lb $s3, result
lb $t2, constCharlwr
li $s0, 0
add $s0, $s0, $s2 # s0 = &arrayA[i]
while: # while loop
add $s0, $s0, $t0 # base address + 1 byte
lb $s1, 0($s0) # load array index value into s1
beq $s1, $t1, outsideWhile # inputArray[i] != '\0'
if1:
bne $s1, $t2, outsideIf # check if inputArray[i] == e
move $s3, $s1 # if true copy s1(inputArray[i] into s3(result)
sb $s3, result
j outsideWhile
outsideIf:
addi $t0, $t0, 1
j while
outsideWhile:
if2:
beq $s3, $t1, else
# Print results
# Print string 2
lw $a0, str2
li $v0, 4
syscall
# Print address of result
la $a0, result
li $v0, 4
syscall
# Print next line
lb $a0, nextline
li $v0, 4
syscall
# Print string 3
lw $a0, str3
li $v0, 4
syscall
# Print result char value
lb $a0, result
li $v0, 4
syscall
# Print next line
lb $a0, nextline
li $v0, 4
syscall
j exitPrgm
else:
# Print No match
lw $a0, str4
li $v0, 4
syscall
# Exit the program by means of syscall.
exitPrgm:
li $v0, 10 # Sets $v0 to "10" to select exit syscall
syscall # Exit
# .data assembler directive
.data
inputArray: .space 256
constCharlwr: .byte 'e'
result: .byte 0
NULL: .byte 0
i: .byte 0
str1: .asciiz "Enter a word to search for letter e: \n"
str2: .asciiz "First match at address "
str3: .asciiz "The matching character is "
str4: .asciiz "No match found\n"
nextline: .asciiz "\n"
Ok, so I figured out my initial problem, I was not using la for my sys calls and once I fixed that I started getting the output that I wanted. The only problem now is I can figure out how to print the actual address of the result. Can someone help me with this.
New Code, Trying a few diffrent things to get the memory address but nothing seems to work.
# Prompt user for input
la $a0, str1
li $v0, 4
syscall
# Get user input and store in input array
la $a0, inputArray
li $a1, 255
li $v0, 8
syscall
# set up registers
lb $t0, i
lb $t1, NULL
la $s2, inputArray
lb $s3, result
lb $t2, constCharlwr
li $s0, 0
add $s0, $s0, $s2 # s0 = &arrayA[i]
while: # while loop
add $s0, $s0, $t0 # base address + 1 byte
lb $s1, 0($s0) # load array index value into s1
beq $s1, $t1, outsideWhile # inputArray[i] != '\0'
if1:
bne $s1, $t2, outsideIf # check if inputArray[i] == e
sb $s1, result
j outsideWhile
outsideIf:
addi $t0, $t0, 1
j while
outsideWhile:
if2:
beq $s1, $t1, else
# Print results
# Print string 2
la $a0, str2
li $v0, 4
syscall
# Print address of result
la $t9, result
li $t8, 4
li $t0, 0
#for:
# bge $t0, $t8 outsideFor
# add $t9, $t9, $t0
# lb $t7, 0($t9)
# sb $t7, resultAddr
# la $a0, resultAddr
# li $v0, 4
# syscall
# addi $t0, $t0, 1
# j for
#outsideFor:
sb 0($t9) resultAddr
la $a0, resultAddr
li $v0, 4
syscall
sb 1($t9) resultAddr
la $a0, resultAddr
li $v0, 4
syscall
sb 2($t9) resultAddr
la $a0, resultAddr
li $v0, 4
syscall
sb 3($t9) resultAddr
la $a0, resultAddr
li $v0, 4
syscall
# Print next line
la $a0, nextline
li $v0, 4
syscall
# Print string 3
la $a0, str3
li $v0, 4
syscall
# Print result char value
la $a0, result
li $v0, 4
syscall
# Print next line
la $a0, nextline
li $v0, 4
syscall
j exitPrgm
else:
# Print No match
la $a0, str4
li $v0, 4
syscall

Reading and Printing User Entered MIPS Array

So I am using MIPS trying to read in several strings entered by a user and then print them, but I am not getting the behavior I expect.
I want to take in 4 bytes of user input (4 characters essentially). In my loop I use the letter 'D' as a signal to exit. The problem is, no matter what I input, when I try to print the very first input later (or even the second, or the third), all I get printed out is the letter 'D' that was used to exit (which should be the last value of the array no?).
.data
mem: .space 256 #256 bytes of space for input
inst .space 5
.text
la $s1, mem #s1 used to take input
la $s2, 0($s1) #Pointer to base address of memory
jal readLoop #Read input loop
lw $a0, 0($s2) #Attempt to read very first saved input
li $v0, 4
syscall
li $v0, 10 #End program
syscall
readLoop:
li $v0, 8 #read string
la $a0, inst #location of input memory
addi $a1, $zero, 5 #length of buffer
syscall
lb $t2,($a0) #used to exit loop
sw $a0, 0($s1) #store input into memory
addi $s1, $s1, 4 #increment memory by 4 bytes
li $t1, 'D'
bne $t2, $t1, readLoop #exit loop on input of a 'D'
jr $ra
I've checked my input as it comes in and even when in the array after saving. It seems my print is the problem, but I could easily be wrong. Any ideas?
The fix was rather easy. Instead of storing the user input into a separate memory location and then putting that location in my array, I simply had the user input be stored directly into my array. See code changes below.
.data
mem: .space 256 #256 bytes of space for input
.text
la $s1, mem #s1 used to take input
jal readLoop #Read input loop
la $a0, mem #Attempt to read very first saved input
li $v0, 4
syscall
li $v0, 10 #End program
syscall
readLoop:
li $v0, 8 #read string
la $a0, mem #set user input as memory location
addi $a1, $zero, 5 #length of buffer
syscall
lb $t2,($a0) #used to exit loop
addi $s1, $s1, 4 #increment memory by 4 bytes
li $t1, 'D'
bne $t2, $t1, readLoop #exit loop on input of a 'D'
jr $ra

MIPS program not giving the right output

I am writing a program to take 10 numbers from user into .word. The program is:
.data
msg1: .asciiz"Ener the number: "
fibs: .word 0,0,0,0,0,0,0,0,0,0
.text
main:
li $t0, 0
loop: # (loop condition, TODO)
bgt $t0,9 ,exit
li $t1, 0 # i = 0
la $a0,msg1 # display prompt string
li $v0,4
syscall
li $v0,5 # read 1st integer into $t0
syscall
move $t2,$v0
lw $t2, fibs($t1) # fib = fibs[i]
addi $t1, $t1, 4 # i++ <= +4
j loop
exit:
move $a0,$t1 # output sum
li $v0,1
syscall
li $v0, 10 # exit the program
syscall
However, the loop never ends and continuously takes the input...I want it to stop and show me the numbers I have input after the 10 integers are entered

read and sum array of integers in assembly

.data
prompt1: .asciiz "\n\n Enter an integer please:"
array: .space 24
linefeed: .asciiz "\n"
enterkey: .asciiz "Press any key to end program."
.text
main:
li $s0, 0
for:
bge $s0, 6, end_for
li $v0, 4 #syscall to print string
la $a0, prompt1 #address of string to print
syscall
li $v0, 5 #syscall to read an integer
syscall
move $t1,$v0
sw $t1,array($t0) #save the number to read into array
addi $t0,$t0,4
addi $s0,$s0,1
j for
end_for:
# print out a line feed
li $v0,4 # code for print_string
la $a0,linefeed # point $a0 to linefeed string
syscall # print linefeed
# wait for the enter key to be pressed to end program
li $v0,4 # code for print_string
la $a0,enterkey # point $a0 to enterkey string
syscall # print enterkey
# wait for input by getting an integer from the user (integer is ignored)
li $v0,5 # code for read_int
syscall #get int from user --> returned in $v0
# All done, thank you!
li $v0,10 # code for exit
syscall # exit program
this is my code.I am trying to store 6 integers in an array and then read again the array of integers and sum them and then printing the sum.I apologize for my bad english
It would be basically the same loop you have just written, but instead of writing the number to the array you would have to read it from the array and sum the values.
E.g.:
li $s0, 0
li $a0, 0
li $t0, 0
forsum:
bge $s0, 6, end_forsum
lw $t1,array($t0) # Load the number from array
addu $a0, $a0, $t1 # Compute the sum
addi $t0,$t0,4
addi $s0,$s0,1
j forsum
end_forsum:
li $v0,1
syscall # Print sum
You can also compute the sum while reading the values from the user input...

For Loop in MIPS using .space

I am trying to make a loop that will add user inputted integers into an array until it fills the array. Every time I typed in a value, QTSPIM spits out 268501016 which I assume to be some random value stored in an register.
To test if my program was going through the whole loop, I added a call to an ascii line when the program reached the branch portion of my beq. The program seemed to be branching even if the values were not (at least to my understanding) equal.
.data
array1: .space 24
str1: .ascii "Type in numbers:"
str2: .ascii "Reached Terminate"
.text
main:
li $t2, 5
li $t3, 0
loop1:
beq $t3, $t2, terminate #branch if equal
la $a0, str1
syscall
ori $v0, $0, 5 #instruction to store user input in v0
syscall #get user input and store it in v0
la $t4, array1 #load the address of the array
addu $t0, $0, $v0 #add v0 (our user input) to $t0
sw 0($t4), t0 #stores the value in $t4 to our array
addi $t3, $t3, 1 #add 1 to t3 (incrementing the counter)
addi $t4, $t4, 4 $add 4 to increment the array 4 bits to the next array slot
jal loop1
terminate:
la $a2, str2 #load the string to check when the program reaches terminate
syscall
ori $v0, $0, 10 # end the program
syscall
The only thing I can think is that my jump call is not going back to loop1, but if this is the case I am unaware how to fix that.
This is 32 bit MIPS code.
You're not setting up the registers properly before the syscalls.
Here there should be an li $v0, 4 before syscall:
la $a0, str1
syscall
If we assume that you're trying to print str2 here, there should be an li $v0, 4 before the syscall, and $a0 should be used instead of $a2:
la $a2, str2 #load the string to check when the program reaches terminate
syscall
This should be sw $t0, 0($t4), not the other way around:
sw 0($t4), t0
This should be j, not jal (jal is used for function calls):
jal loop1

Resources