I have to create a mips code which it has to tell me if a random number (given by the user) is in the array (1) or its not (0). I have two problems, the first one is that the random number that I´m trying to ask to the user (li $v0, 5 -- syscall -- move $t0, $v0) its not working, in fact it does nothing when I assemble it.
The second problem is weird, I have 2 loops (target) and (exit loop), the first one to check if a number is on any of the array position (10 positions) and the second to exit with a 0 if it didn't find the number.
Any ideas?
iterator = 4
N = 10
.data
vector: .word 2, 3, 5, 6, 8, 1, 3, 2, 5, 9
.text
main:
lw $t2, buscador
li $t1, iterator
la $s1, vector
move $s0, $zero
li $v0, 5
syscall
move $t0, $v0
target:
bgt $s0, N, exit_loop
mul $t3, $s0, $t1
addu $t3, $t3, $s1
lw $t3, 0($t3)
addi $s0, $s0, 1
bne $t0, $t3, target
li $s2, 1
move $a0, $s2
li $v0, 1
syscall
exit_loop:
li $s2, 0
move $a0, $s2
li $v0, 1
syscall
li $v0, 10
syscall
There appears to be nothing wrong with your program.
The symbol buscador was not defined, so the program may not have assembled correctly. I commented out the given line. This may have been the only problem.
I did some slight cosmetic cleanup and added some annotations. I also simplified the print integer syscalls [yours would have worked, as is].
I did add an extra jump to a new label exit_program to keep the pass/fail cases separate. Otherwise, you'd have a "fall through" from the pass case to the fail case and you'd get "10" instead of "1" for the pass case.
But, otherwise, I did not (i.e. did not need to) change your logic.
I tested the program and it works on both QtSpim and mars.
Anyway, just to be sure, here's a working version:
iterator = 4
N = 10
.data
vector: .word 2, 3, 5, 6, 8, 1, 3, 2, 5, 9
.text
main:
# NOTE: this symbol was _not_ defined, so spim may have silently not
# run the program
###lw $t2,buscador
li $t1,iterator # get sizeof(vector[0])
la $s1,vector # get vector base address
move $s0,$zero # set vector index to zero
# prompt user for number
li $v0,5
syscall
move $t0,$v0
target:
bgt $s0,N,exit_loop # vector end? if yes, fly
mul $t3,$s0,$t1 # offset = index * iterator
addu $t3,$t3,$s1 # current addr = base + offset
lw $t3,0($t3) # fetch word from vector
addi $s0,$s0,1 # increment the vector index
bne $t0,$t3,target # does value match? if no, loop
# value matches -- output a 1
li $a0,1
li $v0,1
syscall
j exit_program
# we did _not_ find a match -- output a 0
exit_loop:
li $a0,0
li $v0,1
syscall
exit_program:
li $v0,10
syscall
Related
So the assignment is to make a 'calculator' that can store 10 inputs into an array, sort them from smallest to largest value and then add them all together, but no matter how i try the output doesn't print out the numbers and the sum. I'm not sure where I went wrong so if anyone could take a look at it it would be very much appreciated.
.data
array: .space 40 #space for array
msg1: .asciiz "Welcome to sorting calculator!\n"
msg2: .asciiz "Please enter 10 random numbers:\n"
msg3: .asciiz "Sorting your inputs...\n"
msg4: .asciiz "Numbers in ascending order\n"
msg5: .asciiz "Total sum of your input:"
.text
.globl main
main:
#Print string msg1
li $v0,4 # print_string syscall code = 4
la $a0, msg1 # load the address of msg1
syscall
#Print string msg2
li $v0,4 # print_string syscall code = 4
la $a0, msg2 # load the address of msg2
syscall
li $t0, 0 #counter for i
loop1: #First loop
beq $t0, 10, sort #end loop when equal to 10
li $v0, 5 #get input of integer from user
syscall
sw $v0, array($t1) #Store the result in array
addi $t0, $t0, 1 #++i
j loop1
sort:
#Print string msg3
li $v0,4 # print_string syscall code = 4
la $a0, msg3 # load the address of msg3
syscall
li $t0, 0 #counter for i
loop2: #for(int i = 0; i < 10;i++)
li $t1, 1 #counter for k
beq $t0, 10, end_loop2 #end loop when equal to 10
loop3: #for(k=i+1; k<11; k++)
beq $t1, 11, end_loop3 #end loop when equal to 11 (10+1)
lb $t6, array($t0) #load numbers[i] into t6
lb $t7, array($t1) #load numbers[k] into t7
bgt $t6,$t7,if #jump to if when $t6>$t7
addi $t1, $t1, 1 #increment k by 1
j loop3 #jump back to loop3
if:
lb $t2, array($t0) #store numbers[i]
lb $t3, array($t1) #store numbers[k]
sb $t3, array($t0) #numbers[i] = numbers[k]
sb $t2, array($t1) #numbers[k] = temp
j loop3 #jump back to loop3
end_loop3:
addi $t0, $t0, 1 #increment i by 1
end_loop2:
#Print string msg4
li $v0,4 # print_string syscall code = 4
la $a0, msg4 # load the address of msg4
syscall
li $t0,0 #initialize i
loop4:
beq $t0, 10, sec5 #end loop when equal to 10
lb $t5, array($t0) #load numbers[i]
li $v0,1 #print_integer syscall code = 1
addi $a0, $5,0
addi $t0, $t0, 1 #increment t0 by 1
j loop4
sec5:
#Print string msg5
li $v0,4 # print_string syscall code = 4
la $a0, msg5 # load the address of msg5
syscall
li $t0, 0 #counter for i
loopsum: #loop to calculate sum
beq $t0, 10, printsum #end loop when equal to 10
lb $t8, array($t0) #load numbers[i]
add $s7, $s7, $t8 #sum+=numbers[i]
addi $t0, $t0, 1 #increment t0 by 1
j loopsum
printsum:
li $v0,1 # print_integer syscall code = 1
addi $a0, $t4,0
syscall
end:
li $v0, 10
syscall
Basic Debugging Skills
Static Debugging Skills
Write pseudo code in C and make sure it works. It sounds like work but is actually a simplification — it is very hard to find algorithmic & design flaws in assembly language when you're first learning assembly. Small design fixes in pseudo code can also result in larger change in assembly.
Translate your pseudo code into assembly with rigor. Don't "optimize" during translation to assembly — if you want to optimize, do that in the pseudo code. Here I'm talking about, for example, converting the algorithm from using indexing into pointers (do that translation in the pseudo code in C and make sure it works), or, changing a while loop into a repeat until.
Read the assembly code and look for flaws. Compare register sources and targets with variable names from your pseudo code — it is surprisingly easy to have a typo. Run parts of the code in your head. Look for off-by-one errors; make sure loops have proper exit conditions, and maintain proper state for each iteration. Compare with your pseudo code and make sure each piece is present and in the right place.
Dynamic Debugging Skills
Anyone writing assembly language should be able to single step and watch/verify their code execute.
Single step and verify that each instruction does what you expect. Most instructions have a main effect: change the value of a register, or change the value of memory. And all instructions tell the processor what instruction to run next. So, we need to verify the main effect and the control flow (what instruction comes next). (syscalls can change multiple memory locations and offer a return result as well.)
When you're debugging fresh code that's never been tested, use the smallest possible input to make debugging simple. Expect typos in your code, such as wrong register source, wrong register target, etc..
As you evolve your program, use breakpoints to skip over code that you already know is working, then single step the new code from there.
When you can, use the smallest possible input and try debugging with that first, then make it larger. In this case, you could change your 10 to a 1 or 2 to make it easier to single-step and find the most basic bugs.
I found your first bug after single-stepping of less than 30 instructions from the beginning. You should have been able to do this.
The user entered data is being stored in the first word of your array. Since you neither initialize nor increment the index $t1, all the words are stored in the same place, each one overwriting the prior. Maybe should have been $t0, but that would have to be scaled for word size. So, maybe you're missing an instruction to scale $t0 and put that value into $t1.
I am writing a program that given an array, it prints out array value and swap two elements of choice by users. This is the code:
# Declare main as a global function
.globl main
# Declare the data
.data
list:
.align 4 # Forces a word to line up at boundary/4
.word 5, 17, 43, 22, 120, 3 # A six-element array
endList:
space:.asciiz " "
newLine: .asciiz "\n"
msg1:.asciiz "Array is: "
msg2:.asciiz "Enter fisrt index to swap: "
msg3:.asciiz "Enter second index to swap: "
msg4:.asciiz "Array after swapping is: "
#.text assembler directive to place the code
.text
# Start the program at main
main:
la $s1, list # Load beginning address of array
into register $s1
la $s2, endList # Load end address of array into register $s2
la $a0, msg1 # Load address of message string into $a0
li $v0, 4 # Load print string system call code into $v0
syscall # System call to print
jal printLoop
jal swap
# Exit
li $v0, 10
syscall
printLoop:
beq $s1, $s2, printDone # Check when array end, go to done
lw $a0, ($s1) # Load word at address of $s1 into $a0
li $v0, 1 # Load print integer system call code
into $v0
syscall # System call to print number
la $a0, space # Load address of space stringinto $a0
li $v0, 4 # Load print string system call code into $v0
syscall # System call to print a space
addi $s1, $s1, 4 # Advance array pointer to the next element
j printLoop # Loop back to next element
printDone:
j $ra
swap:
la $a0, newLine # Print a new line
li $v0, 4
syscall
la $a0, msg2 # Print a message to ask for first index to swap
li $v0, 4
syscall
li $v0, 5 # Get user input, save into $s3
syscall
addi $s3, $v0, 0
la $a0, msg3 # Print a message to ask for second index to swap
li $v0, 4
syscall
li $v0, 5 # Get user input, save into $s4
syscall
addi $s4, $v0, 0
sll $t0, $s3, 2 # Multiply first index by 4 to get its offset
add $t0, $s1, $t0 # Get the address of the first index
sll $t1, $s4, 2 # Multiply second index by 4 to get its offset
add $t1, $s1, $t1 # Get the address of the second index
lw $t2, ($t0) # Load first number at address contained in $t0 into $t2
lw $t3, ($t1) # Load second number at address contained in $t1 into $t3
sw $t2, ($t1) # Store first number into address of second number
sw $t3, ($t0) # Store second number into address of first number
move $a0, $t0
li $v0, 4
syscall
move $a0, $t1
li $v0, 4
syscall
j $ra
When I step through the code using QtSpim, these lines seem to be giving problems:
lw $t2, ($t0)
lw $t3, ($t1)
The values in $t2 and $t3 should be integer values given by the array. For example, if user specifies index 1 and 2, values in $t2 and $t3 should be 5 and 17. Instead it showed weird numbers: 1634890305 and 1936269433 (decimal) in my version.
What is going wrong? I would appreciate any help!
Printloop changes $s1, so when swap uses it, it points at the list end.
I am new to mips and I want to print out the max and min of an 8 element array. I saw a question similar to mine but it was done by calling a function readArray and I want to do it without that. Here's what I have so far. I just wanna know whether what I have right now is correct and how to end the loop. Like what do I write to print the correct values
.data
X: .word 1, 2, 3, 4, 5, 6, 7, 8
globl main
.text
main:
la $t0, X
lw $s0, 0($t0) #Sets Max to first value in array
move $s1, $s0 #Sets Min to first value in array
addi $t1, $0, 0 #Sets the counter to 0
li $t1, 0 #Index for the array
loop:
bge $t0, 8 EndLoop
bgt X($t1), $s0, SetMax
blt X($t1), $s1, SetMin
addi $t1, $t1, 4 #Increases the index for the array
addi $t0, $t0, 1 #Increments the counter
SetMax:
move $s0, X($t1)
j loop
SetMin:
move $s0, X($t1)
j loop
EndLoop:
li $v0, 1
addi $s0, $s0, 0
addi $si, $s1, 0
syscall
Am I doing something wrong. Here is the original problem:
Write MIPS code to search through an array X[8] words to find the minimum and maximum values. Store the maximum in register $s0 and the minimum in $s1. Print to screen min and max.
Thanks for the help!
To print an integer you need $v0 to be 1 and $a0 to be equal to the integer you want to print.So point to the register that you have saved the value.
li $v0 1
la $a0 ($s0)
syscall
the same process for $s1 .
To end the program:
li $v0 10
syscall
You may want to make it more visible so print a space or tab between them. Link with some system calls
enter code here I'm trying to count the number of elements in this array that are divisible by four, currently it prints out the number of times the program loops. For some reason the program calls mod every time. Can anyone identify why this might be happening?
.data
arr: .word 5, 4, 8,12, 13, 16, 18, 20, 24,23,0
msg: .asciiz "Elements Divisible By 4 : "
four: .word 4
.text
lb $s4, four
.globl main
main:
addi $t0, $0, 0 # clear i
addi $t1, $0, 0 # clear sum
ori $t2, $0, 11 # Initializing t2 to its constant value 10
la $t3, arr # load address of array into t3
loop:
slt $t4, $t0, $t2 # compare, $t4 = i < sum ? 1 : 0
beq $t4, $0, end # if i is not < 11, exit the loop
lw $t4, 0($t3) # load current array element into t4
andi $t4, $t4, 3
beq $t4, $zero, mod
j loop
mod: # if-else exit
add $t1, $t1, 1 # add it to sum
add $t0, $t0, 1 # increment i
add $t3, $t3, 4 # increment current array element pointer
j loop
end:
addi $v0, $0, 4 # Now we print out result: string
la $a0, msg
syscall
addi $v0, $0, 1 # followed by the actual sum (which is in t1)
add $a0, $t1, $0
la $t5, exit
syscall
exit:
j exit
Working version
.data
arr: .word 12, 4, 8, 12, 13, 16, 18, 20, 24, 23, 0
msg: .asciiz "Counter "
fourMod: .word 4
.text
lb $s1, fourMod
.globl main
main:
addi $t0, $0, 0 # clear i
addi $t1, $0, 0 # clear sum
ori $t2, $0, 10 # Initializing t2 to its constant value 10
la $t3, arr # load address of array into t3
loop:
slt $t4, $t0, $t2 # compare, $t4 = i < sum ? 1 : 0
beq $t4, $0, end # if i is not < 10, exit the loop
lw $t4, 0($t3) # load current array element into t4
andi $t4, $t4, 3
beq $t4, $zero, mod
add $t0, $t0, 1 # increment i
add $t3, $t3, 4 # increment current array element pointer
j loop
mod:
#add to the divisible by 4 counter?
add $s2, $s2, 1
add $t0, $t0, 1 # increment i
add $t3, $t3, 4 # increment current array element pointer
j loop
end:
addi $v0, $0, 4 # Now we print out result: string
la $a0, msg
syscall
addi $v0, $0, 1 # followed by the actual sum (which is in t1)
add $a0, $s2, $0
la $t5, exit
syscall
exit:
j exit
You never tell your program not to execute the code after mod::
add $t3, $t3, 4 # increment current array element pointer
<--- There's nothing here to prevent the execution to continue with the below add
mod:
add $s2, $s2, 1
Use a branch instruction if you want to skip over some code. Or in your case what you want is probably a j loop.
Another thing is that you're doing an unnecessary division, which often is a relatively slow operation. Checking whether an integer is a multiple of four can be done by testing the two least significant bits:
andi $t4, $t4, 3 # Isolate the two least significant bits
beq $t4, $zero, mod # We've got a multiple of 4 if those two bits are zero
Edit: With your updated code you're still incrementing your "is divisible" counter on every iteration. It would probably be best if you inverted your branch condition and changed that part of the code into:
andi $t4, $t4, 3
bne $t4, $zero, not_divisible
add $t1, $t1, 1 # add it to sum
not_divisible: # if-else exit
add $t0, $t0, 1 # increment i
.... # omitted for brevity
I'm working on some MIPS code for my Computer Organizations class, and well I just can't seem to get the MIPS to work correctly and there's not that many MIPS resources online. I'm running the code on PCSPIM. The code is supposed to add 10 to the contents of array2 and store them in array1 and then print array 1. Reworked the code works properly now.
.text
main:
la $t0, array1
la $t1, array2
la $s0, valuec
li $s2, 6
add $t6, $zero, 1 #i = 1
Loop:
addi $t6, $t6, 1 #i++
lw $t2, ($t0)
lw $t5, ($t1)
lw $s1, ($s0)
addu $t2, $t5, $s1
sw $t2, ($t0)
add $t0, $t0, 4
add $t1, $t1, 4
li $v0, 1
move $a0, $t2
syscall
blt $t6, $s2, Loop
li $v0, 10
syscall
.data
array1: .space 20
array2: .word 1,2,3,5,9
valuec: .word 10
PCSPIM prints 0 5 times and returns Exception 7 [Bad data Address] occured and ignored
This is homework so I'm only going to give you clues for now and add to it as you go. A couple of things:
1/ You need to tell us what it's supposed to do. That's the most important thing.
2/ You store array1 address into t0 then reuse t0 within the first loop.
3/ You appear to be confused about addresses and the contents of those addresses ("la $s0, valuec" and "addu $t0, $t1, $s0").
UPDATE:
Actually I have to sign off for a while, so I'll post my solution so as to not leave you in the lurch.
The confusion I referred to before was the fact that you're loading up two addresses into $t1 and $s0, then adding them together to get another address - this is likely to be well beyond your data area (you should really be adding an address and an offset).
That's basically the problem you have with your code (both the zeros being printed and the crash). Your best bet would be to fix that and refer to my code below only as a last resort to see how I would have done it. Copying code will not help you in the long term and you would be wise to assume your educator is also checking all web sites for plagiarism.
This is the code I've come up with (quickly, so you'll need to test it - it may have bugs). I suggest you read the comments in great detail to understand what it's doing.
I'll be back in a few hours to see how you're doing. Cheers.
.text
main:
# Initialization of array pointers and loop
la $t0, array1 # address of array 1
la $t1, array2 # address of array 2
li $t2, 1 # element number
li $t3, 6 # upper limit of elements
# Process each word in array 2, adding 10 and placing
# into array 1.
Loop:
lw $t3, 0($t1) # get word from array 2
addi $t3, $t3, 10 # add 10 to word
sw $t3, 0($t0) # store word into array 1
addi $t0, $t0, 4 # move to next entry in array 1 and 2
addi $t1, $t1, 4
addi $t2, $t2, 1 # increment element number
blt $t2, $t3, Loop # loop until all elements done
# Initialize printing loop by going back to start of array 1
la $t0, array1 # address of array 1
li $t2, 1 # element number
# Loop through array 1, printing each element.
pLoop:
lw $t2, 0($t0) # get word from array 1
li $v0, 1 # 'print' command code
move $a0, $t2 # needs value in $a0
syscall # print it
addi $t0, $t0, 4 # move to next entry in array 1
addi $t2, $t2, 1 # increment element number
blt $t2, $t3, Loop # loop until all elements done
li $v0, 10 # 'terminate' command code
syscall # exit
# Data arrays for array 1 and 2
.data
array1: .word 0,0,0,0,0
array2: .word 1,2,3,4,5
There's a number of possible issues, but the most obvious/likely is that you aren't returning from main before the start of your data section.
jr ra