Problem with MIPS division - mips

I need help with debugging the following code. I've tried like 10 times or more but I still don't understand why I got such a weird output as seen below:
Enter a: 5
Enter b: 2
a/b = 268501012 (<--- weird output)
# task4partial.asm
# Given positive integers a and b, output a/b and a%b.
.data
str1: .asciiz "Enter a: "
str2: .asciiz "Enter b: "
str3: .asciiz "a/b = "
str4: .asciiz "a%b = "
newline: .asciiz "\n"
.text
main: li $v0, 4 # system call code for print_string
la $a0, str1 # address of str1
syscall # print str1
#get the first number from user, put it into $s0
li $v0, 5 # system call code for read_int
syscall # read an integer into $v0 from console
add $s0, $v0, $zero # copy $v0 into $s0 (a)
#read print_string for str2
li $v0, 4 # system call code for print_string
la $a0, str2 # address of str1
syscall # print str1
# get second number from user, put it into $t1
li $v0, 5 #load syscall for read_int
syscall #make the syscall
move $s1, $v0 #move the number read into $s1(b)
#do the calculations
div $s0, $s1 #diving $s0 by $s1
mflo $t0 #storing value of lo(quotient) in
#register $t0
mfhi $t1 #storing value of hi(remainder) in
#register $t1
#read print_string for str3
li $v0, 4 # system call code for print_string
la $a0, str3 # address of str1
syscall # print str1
#print a/b
li $v0, 1 #load syscall print_int into $v0
move $t2, $t0 #move the number to print into $t2
syscall
#end of program
li $v0, 10 #system call code for exit
syscall

The mistake is in this line: move $t2, $t0 #move the number to print into $t2
The argument for the print_int syscall-routine has to be put into $a0, not into $t2.

Related

How do I continue my program after the "##"

So I have made a program which allows users to put how many hello world that they want and after ## there is another function but that won't play out instead the program just closes.
.data
n: .space 4
msg: .asciiz "Hello World"
prom1: .asciiz "How many Hello World want to be printed: "
mychar1:.byte 'a'
out_string: .asciiz "\nHello World\n"
prom: .asciiz "Type a number: "
mychar: .byte 'm'
res: .asciiz "Result is: "
nl: .asciiz "\n"
.text
main: li $v0, 4
la $a0, msg
syscall
li $v0, 4 # print str
la $a0, nl # at nl
syscall
li $v0, 4 # print str
la $a0, nl # at nl
syscall
li $v0, 4
la $a0, prom1 # Load address of first prompt
syscall
li $v0, 5 # Read int from user
syscall
li $t1, 0 # Load 0 into $t1 for comparison
move $t0, $v0 # Move the user input to $t0
loop:
beq $t1, $t0, end # Break If Equal: branch to 'end' when $t1 == $t2
li $v0, 4
la $a0, out_string # Load address of output string
syscall
add $t1, $t1, 1 # Increment $t1
j loop # Jump back up to loop
end:
li $v0, 10 # Load syscall 10 to indicate end of program
syscall
##
li $v0, 4 # print str
la $a0, nl # at nl
syscall
li $v0, 4 # print str
la $a0, prom # at prom
syscall
li $v0, 5 # read int
syscall
sw $v0, n # store in n
li $v0, 4 # print str
la $a0, res # at res
syscall
li $v0, 1 # print int
lw $t0, n # n
sub $t1, $t0, 1 # n-1
mul $t0, $t0, $t1 # *
sra $a0, $t0, 1 # /2
syscall
li $v0, 4 # print str
la $a0, nl # at nl
syscall
li $v0, 4 # print str
la $a0, nl # at nl
syscall
li $v0, 10 # exit
syscall
In this spot here
end:
li $v0, 10 # Load syscall 10 to indicate end of program
syscall
You are calling a syscall with 10 in the $v0 register.
This tells the computer to stop the program. So in this case you are just stopping the program before the rest of the code is executed.
Instead you could do this
loop:
beq $t1, $t0, endloop
li $v0, 4
la $a0, out_string # Load address of output string
syscall
add $t1, $t1, 1 # Increment $t1
j loop # Jump back up to loop
endloop:
# Put rest of code here
This is just the way to end the loop and continue.
Then at the end of the program you can put the syscall 10

Asking user to input two numbers, store them in memory, doing addition and substraction and display both result

I'm new to MIPS, and I'm working on this question, my code wold assemble, but after I hit the run buttom and entered the first number, it would show a runtime exception: Runtime exception at 0x00400018: address out of range 0x00000000
I don't understand what's happening to my code, can anyone help me?
.data
str1: .asciiz "Enter number 1: "
str2: .asciiz "Enter number 2: "
str3: .asciiz "The sum of the two number is: "
str4: .asciiz "The difference of the two number is: "
num1: .word 4
num2: .word 4
.text
.globl main
main:
la $t0, str1
li $v0, 4 #syscall code for print_str
la $a0, ($t0) #address of string to print
syscall #print str1
la $s0, num1
li $v0, 5 #syscall code for read int
syscall #read int
sw $s0, ($v0) #store the enterd value in num1
la $t1, str2
li $v0, 4 #syscall for print_str
la $a0, ($t1) #address of string to print
syscall #print str2
la $s1, num2
li $v0, 5 #syscall code for read int
syscall #read int
sw $s1, ($v0) #store the entered value in num2
add $s2, $s0, $s1 #add num1 and num2
la $t2, str3
li $v0, 4 #syscall for print_str
la $a0, ($t2) #address of str3
la $a1, ($s2) #address of the sum
syscall #print str3 and the sum
sub $s3, $s0, $s1 #substract num1 and num2 ERROR COULD BE HERE
la $t3, str4
li $v0, 4 #syscall for print_str
la $a0, ($t3) #address of str4
la $a1, ($s3) #address of the difference
syscall #print str4 and the difference
li $v0, 10 #exit
syscall
Error in C:\Users\Desktop\exercise2.s line 18: Runtime exception at 0x00400018: address out of range 0x00000000
Go: execution terminated with errors.
Many problems in your code.
la $a0, ($t0) is incorrect. The assembler should warn you. la is a two instructions macro that` loads an address from a label, while $t0 is a register (that already holds the value of str1).
It should be replaced by la $a0, str1 or (much better because it is a a unique instruction) mov $a0, $t1 as you already did this computation for $t1. You have the same problem for str2, str3 and str4.
But there is no need to use a temporary register and you could directly do the computation in $a0.
There is another problem. According to documentation after syscall 5 "$v0 contains integer read". So the sw $s0, ($v0) after reading the ints are incorrect. What should be stored is $v0 and the store address is num1 and has already been loaded in $s0.
add $s2, $s1, $s0 is also incorrect, as $s0 and $s1 values are integer addresses, not integer values.
Last, you cannot print at once a string and an integer. It must be done in two syscalls : syscall 4 to print a string and syscall 1 to print the integer.
.data
str1: .asciiz "Enter number 1: "
str2: .asciiz "Enter number 2: "
str3: .asciiz "The sum of the two number is: "
str4: .asciiz "The difference of the two number is: "
num1: .word 4
num2: .word 4
.text
.globl main
main:
la $a0, str1
li $v0, 4 #syscall code for print_str
syscall #print str1
li $v0, 5 #syscall code for read int
syscall #read int
mov $s0, $v0 ## keep the value of int in a register
la $t1, num2
sw $v0, ($t1) #store the entered value in num2
li $v0, 4 #syscall for print_str
la $a0, str2 #address of string to print
syscall #print str2
li $v0, 5 #syscall code for read int
syscall #read int
mov $s1, $v0 ## keep the value of int in a register
la $t1, num2
sw $v0, ($t1) #store the entered value in num2
add $s2, $s0, $s1 #add num1 and num2
la $a0, str3
li $v0, 4 #syscall for print_str
syscall #print str3
li $v0, 1 #syscall for print integer
mov $a0, $s2 #value of the sum
syscall #print sum
sub $s3, $t0, $t1 #substract num1 and num2
la $a0, str4
li $v0, 4 #syscall for print_str
syscall #print str4
li $v0, 1 #syscall for print integer
mov $a0, $s3 #value of the diff
syscall #print diff value
BTW, storing the integers is useless. I kept them because it is in the title of the question, but it you just need the sum and diff, the sw instructions and corresponding la can be suppressed.

MIPS: how can I apply the integer which users input into arithmetic function?

This is my first time coding PCSPIM. I find that there is a little trouble with my code.
.data
user_input: .asciiz "\n\nEnter an Integer for the value of n: "
result_display: .asciiz "\nThe sum from 0 to n is "
Greeting: .asciiz "\n\nThank you!"
.text
main:
#user input
li $v0, 4
la $a0, user_input
syscall
#allow user input
li $v0, 5
syscall
#store the input value into t8
move $t8, $v0
#calculation
addi $s0, $zero, $t8
I wish to use the integer value ($t8) that users input into the #calculation section, but it ends up with error.
addi $t0, $zero, 0
loop1:
add $t0, $t0, $s0
addi $s0, $s0, -1
bne $s0, $zero, loop1
nop
nop
# Display the result
li $v0, 4
la $a0, result_display
syscall
# Print out the result
li $v0, 1
move $a0, $t0
syscall
# Greets the user
li $v0, 4
la $a0, Greeting
syscall
# Exit the program
li $v0, 10
syscall
Sorry for my broken English.
The error is in the way you are using the "addi" instruction. The instruction requires an immediate (number) value to be passed as the third operand and not an architectural register. If you update the "addi" instruction to "addu" the code should work.

MIPS multiplication using addition

sorry, I try to multiply two integers but it doesn't work. I can't find where the problem is.Maybe because of register' names but I don't know how to correct it. I correct many times but it is not successful. Could anyone give me some points?
.data
prompt1: .asciiz "Please enter the first signed (decimal) integer: "
prompt2: .asciiz "Please enter the second signed (decimal) integer: "
result_msg: .asciiz "The result of these two 16-bit integers\' multiplication is: "
.text
.globl main
main:
li $v0, 4 #print prompt
la $a0, prompt1
syscall
li $v0, 5 #read multiplicand
syscall
move $s0, $v0
li $v0, 4 #print prompt
la $a0, prompt2
syscall
li $v0, 5 #read multiplier
syscall
move $s1, $v0
Mult: ori $t0,$zero,1 #mask
move $s3, $0 #initialize the result register
move $t1, $0
loop: beq $s1, $zero, end #if the multiplier is 0 then finished
and $t1, $t0, $s1 #mask
beq $t1, 1, mult_add
beq $t1, 0, shift
mult_add: addu $s3, $s3, $s0 #add to get product
shift:
sll $s0, $s0, 1 #shift multiplicand left
srl $s1, $s1, 1 #shift multiplier right
j loop
end:
jr $ra
result: #input the print_string
li $v0, 4
la $a0, result_msg
syscall
exit:
li $v0, 1 #input result
move $a0, $s3
syscall
li $v0, 10 #exit
syscall
Inspecting your code I see that you jump to label end when you are done multiplying.
The instruction at that label issues a jr $ra which "returns from a function", but I guess you just want to print the result and exit.
Therefore I'd suggest you remove that instruction so as to print the result and exit and maybe remove label result as it is not used anywhere in your code.

MIPS Calculator

I'm trying to finish up this MIPS calculator, super basic, my first mips program. It doesn't have to handle overflow or anything like that, just has to work on small, positive numbers.
I've not checked my algorithms for multiply and divide, because I am just trying to get add working.
I cannot for the life of me figure out why the ints will not read in and also I'm getting a memory out of bounds when I call lb $a0, op to display the operator for output and don't understand why.
I'm new to this so anything is probably helpful. Thanks in advance.
.data
# const string for welcome
welc: .asciiz "Welcome to SPIM Calculator 1.0!\n"
p_int: .asciiz "\nPlease give an integer: "
p_op: .asciiz "\nPlease give an operator: "
i_err: .asciiz "\nInput Incorrect, bad operator!\n"
again_str: .asciiz "Another calculation? (y/n)"
rmndr: .asciiz " r: "
new_line: .asciiz "\n"
int1: .word 1 # space to hold int 1
int2: .word 1 # space to hold int 2
raw_in: .space 1 # space to hold raw input
op: .space 1 # space to hold operator char
a_char: .space 1 # space to hold again char
out: .word 1 # space to hold output
remain: .word 1 # space to hold remainder
#operator constants
c_plus: .ascii "+" # const for +
c_min: .asciiz "-" # const for -
c_mult: .asciiz "*" # const for *
c_divi: .asciiz "/" # const for /
c_eq: .asciiz "=" # const for =
c_no: .asciiz "n" # const for n
.text
.globl main
main: li $v0, 4 # syscall 4, print string
la $a0, welc # give argument: string
syscall # actually print string
calc: la $t6, remain # load remainder variable
move $t6, $zero # store 0 in remainder (reset)
li $v0, 4 # syscall 4, print string
la $a0, p_int # give argument: string
syscall # actually print string
li $v0, 5 # tell syscall we want to read int 1
syscall # actually read in int 1
la $s1, int1 # load int1 into $s1
move $s1, $v0 # copy the integer from $v0 to int1
li $v0, 4 # syscall 4, print string
la $a0, p_int # give argument: string
syscall # actually print string
li $v0, 5 # tell syscall we want to read int 2
syscall # actually read in int 2
la $s2, int2 # give $s2 the address to hold int 2
move $s2, $v0 # copy the integer from $v0 to $s2
li $v0, 4 # syscall 4, print string
la $a0, p_op # give argument: string
syscall # actually print string
li $v0, 8 # tell syscall we want to read operator
la $a0, op # give $a0 the address to hold the operator
syscall # actually read in operator
lb $t0, op # load the first byte of op
li $t1, '+' # load const for plus
li $t2, '-' # load const for minus
li $t3, '*' # load const for multiplying
li $t4, '/' # load const for dividing
la $s0, out # load out to $s0
beq $t0, $t1, plus # we're adding
beq $t0, $t2, minus # we're subtracting
beq $t0, $t3, multi # we're multiplying
beq $t0, $t4, divi # we're dividing
# else
j error # incorrect input
plus: add $s0, $s1, $s2 # add our ints, store in $t0
j print
minus: sub $s0, $s1, $s2 # subtract our ints, store in $t0
j print
multi: slt $t1, $t2, $s2 # if our counter is less than int2, set $t1 to 1
beq $t1, $zero, print # if we've reached int2, we're done
add $s0, $s1, $s1 # add int1 and int1, store in out
j multi # loop
divi: la $t0 remain # load remainder into $t0
move $t0, $s1 # set remainder to dividend
add $s0, $zero, $zero # set out to 0, just in case
loop: slt $t1, $t0, $s2 # if remainder is less than divisor, set 1
beq $t1, $zero, print # if we're done branch to done
sub $t0, $t0, $s2 # sub divisor from remainder, store in remainder
addi $s0, $s0, 1 # increment quotient by 1
j loop # loop
print: li $v0, 1 # tell syscall we want to print int
la $a0, int1 # give syscall int1 to print
syscall # actually print int
li $v0, 4 # tell syscall we want to print string
lb $a0, op # tell syscall we want to print operator
syscall # actually print string
li $v0, 1 # tell syscall we want to print int
la $a0, int2 # give syscall int2 to print
syscall # actually print int
li $v0, 4 # tell syscall we want to print string
la $a0, c_eq # tell syscall we want to print operator
syscall # actually print string
li $v0, 1 # tell syscall we want to print integer
la $a0, out # give syscall our output
syscall # actually print int
la $t0, remain # load remainder
beq $t0, $zero, again # if we have no remainder, finish printing
li $v0, 4 # tell syscall we want to print string
la $a0, rmndr # tell syscall we want to print remainder string
syscall # print "r: "
li $v0, 1 # tell syscall we want to print int
la $a0, remain # give syscall our remainder to print
syscall # print remainder
again: li $v0, 4 # tell syscall we want to print string
la $a0, new_line # tell syscall to print new line
syscall
la $a0, again_str # load prompt for again string for syscall
syscall
li $v0, 8 # tell syscall we want to read string
la $a0, a_char # tell syscall to put it in $a0
syscall
lb $t0, a_char
li $t1, 'n' # get n char so we can compare
beq $t0, $t1, exit # if we are done, exit
#else loop
j calc # jump to beginning
error: li $v0, 4 # tell syscall we want to print string
la $a0, i_err # give syscall what to print
syscall # actually print
j again # go to prompt for retry
exit: li $v0, 10 # exit code
syscall #exit!
screenshot
The problem is that you don't use the appropriate instruction to handle memory.
Instead of move you should use sw (store word). This code will not store the int into int1:
la $s1, int1 # load int1 into $s1
move $s1, $v0 # copy the integer from $v0 to int1
instead, you should write:
la $s1, int1 # load address of int1 into $s1
sw $v0, 0($s1) # copy the integer from $v0 to int1
Like storing, loading from memory require two instructions:
la $s1, p_op # or whatever register you choose to use
lb $a0, 0($s1) # load byte from the address stored in $s0 (in index 0)
if you want to load the address of p_op into $a0, you should use la $a0, p_op, not lb