How to print an string without the newline Mips Assembly language - mips

I am trying to get the output in the same line with the result(string). I have found examples, but none of them explained the process. I know that the string has to be store in memory and then access it through bit by bit, but I got lost in the process.
.data
prompt: .asciiz "Enter your name: "
name: .space 101
result: .asciiz " ...that's the name"
.text
.globl main
main:
la $a0, prompt
li $v0, 4
syscall
la $a0, name # Get the input
li $v0, 8
li $a1,101
syscall
la $a0, name # print the result
li $v0, 4
syscall
la $a0, result
li $v0, 4
syscall
li $v0,10
syscall

The problem comes from that, when you read in the input the new line will be read also, so it has to be removed in order to achieve your needs.
This is one way to do it:
.data
prompt: .asciiz "Enter your name: "
name: .space 101
result: .asciiz " ...that's the name"
.text
.globl main
main:
la $a0, prompt
li $v0, 4
syscall
la $a0, name # Get the input
li $v0, 8
li $a1,101
syscall
addi $t1, $t1, 0 # len = 0
len_to_new_line:
lb $t2, ($a0) # t2 = *a0
beq $t2, '\n', end # if t2 == '\n' -> stop
addi $t1, $t1, 1 # len++
addi $a0, $a0, 1 # a0++
b len_to_new_line
end:
la $a0, name
add $a0, $a0, $t1
sb $zero, ($a0) # overwrite '\n' with 0
la $a0, name # print the result
li $v0, 4
syscall
la $a0, result
li $v0, 4
syscall
li $v0,10
syscall
Output
Enter your name: David
David ...that's the name
EDIT: The len is not even needed and code can be reduced to this (only the changed part)
len_to_new_line:
lb $t2, ($a0) # t2 = *a0
beq $t2, '\n', end # if t2 == '\n' -> stop
addi $a0, $a0, 1 # a0++
b len_to_new_line
end:
sb $zero, ($a0) # overwrite '\n' with 0

Related

MIPS - Prints the input next to output

I'm learning MI trying to write a factorial program in MIPS Assembly code for which
3! = 6 (my output shows it 36)(input next to output)
4! = 24(my output shows it as 424)
Here is my code. What should I do to get rid of printing the input?
.data
num: .asciiz "\nPlease enter a number: "
num2: .asciiz"\nPlease give your second number : "
respon: .asciiz "\nThe factorial of the entered number is: "
nl: .asciiz"\n"
.text
fact:
beqz $a0,return1
li $v0, 1
li $t0, 1
fact_loop:
bgt $t0, $a0, end_fact_loop
mul $v0, $v0, $t0
addi $t0, $t0, 1
j fact_loop
end_fact_loop:
jr $ra
return1:
li $v0, 1
jr $ra
main:
li $v0, 4
la $a0, num
syscall
li $v0, 5
syscall
move $t0, $v0
li $v0, 4
la $a0, respon
syscall
li $v0, 1
move $a0, $t0
syscall
jal fact
move $t0, $v0
li $v0, 1
move $a0, $t0
syscall
li $v0, 4
la $a0, nl
syscall
################################
li $v0, 4
la $a0, num2
syscall
li $v0, 5
syscall
move $t0, $v0
li $v0, 4
la $a0, respon
syscall
li $v0, 1
move $a0, $t0
syscall
jal fact
move $t0,$v0
li $v0, 1
move $a0, $t0
syscall
li $v0, 10
syscall
To get rid of printing the input you have to remove the syscall you are issuing to print them.
That is, before jal-ing fact (both times) you are issuing these instructions:
li $v0, 1
move $a0, $t0
syscall
Just, remove the first and third instruction and keep the move as you use it on your fact routine:
move $a0, $t0
A few suggestions:
Add a comment to each functional chunk of code.
Use a single-step to debug so you can see what's happening where.
Simplify the code to a minimal failing example. If you have two chunks of code both exhibiting the same problem, remove one of them and focus on the first without distractions and noise from the second.
Prune unnecessary code. For example, the return1: block and beqz $a0,return1 are superfluous because the main factorial loop will exhibit the same behavior automatically -- you don't need to handle $a0 == 0 specially.
Having followed these tips, I wound up with the following program:
.data
num: .asciiz "\nPlease enter a number: "
num2: .asciiz "\nPlease give your second number : "
respon: .asciiz "\nThe factorial of the entered number is: "
nl: .asciiz "\n"
.text
fact:
li $v0, 1
li $t0, 1
fact_loop:
bgt $t0, $a0, end_fact_loop
mul $v0, $v0, $t0
addi $t0, $t0, 1
j fact_loop
end_fact_loop:
jr $ra
main:
# print prompt "Please enter a number: "
li $v0, 4
la $a0, num
syscall
# get user input for first fact call
li $v0, 5
syscall
move $t0, $v0
# call fact(n)
move $a0, $t0
jal fact
move $t0, $v0
# print "factorial is..."
li $v0, 4
la $a0, respon
syscall
# print the result of fact(n)
li $v0, 1
move $a0, $t0
syscall
# print newline
li $v0, 4
la $a0, nl
syscall
# exit program
li $v0, 10
syscall
The problem of double-printing is caused by this code:
li $v0, 1
move $a0, $t0
syscall
The move $a0, $t0 is necessary to set up the fact call, but we don't want li $v0, 1 and syscall, which prints the argument without a newline before the result of fact, causing your unwanted output.
A good technique to prevent this in the future is ensuring your argument set-up for the function call to fact happens right before the jal.
I'll leave it as an exercise to adapt this to your second chunk of code, which has the same extra syscall to service 1 (print integer).

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

Sum of two numbers in MIPS

I'm trying to practice my coding skill in MIPS (this is my first time ever learning an assembly language). I wrote this code below to sum up two user's inputs, and it is correct. However, the code is quite long..so, is there any way to optimize this code so it will be shorter? i need some suggestions. Thanks
.data
n1: .asciiz "enter your first number: "
n2: .asciiz "enter your second number: "
result: .asciiz "result is "
.text
#getting first input.
la $a0, n1
li $v0, 4
syscall
li $v0, 5
syscall
move $t0, $v0
#getting second input.
la $a0, n2
li $v0, 4
syscall
li $v0, 5
syscall
move $t1, $v0
#calculate and print out the result.
la $a0, result
li $v0, 4
syscall
add $t3, $t0, $t1
move $a0, $t3
li $v0, 1
syscall
#end program.
li $v0, 10
syscall
I also have wrote a program to calculate a factorial number. There are better ways to do this?
.data
str: .asciiz "Enter a number: "
result: .asciiz "The result is: "
.text
la $a0, str
li $v0, 4
syscall
li $v0, 5
syscall
move $s0, $v0 # move N into s0
li $s2, 1 # c = 1
li $s1, 1 # fact = 1
LOOP:
blt $s0, $s2, PRINT # if (n < c ) print the result
mul $s1, $s1, $s2 # fact = fact * c
add $s2, $s2, 1 # c = c + 1
j LOOP
PRINT:
la $a0, result
li $v0, 4
syscall
add $a0, $s1, $zero
li $v0, 1
syscall
li $v0, 10
syscall
The programs look ok, except for the use of the temporary registers $t0,...,$t9. These registers are not guaranteed to be preserved when another function is called, or when a syscall is issued. The $s0,...,$s7 registers are preserved across calls.
You need to replace: move $t0, $v0 with move $s0, $v0; move $t1, $v0 with move $s1, $v0 and add $t3, $t0, $t1 with add $s3, $s0, $s1.

What does the following QtSPIM/MIPS code do

What does the following QtSPIM/MIPS code do. Describe by referring to the functions of various blocks of the code (Block1, Block2, …).
Answer the questions in front of certain instructions.
Block1:
.text
main:
li $s4, 0
la $a0, input
li $v0, 4
syscall
li $v0, 5
syscall
move $t0, $v0 #Why do we need this?
Block2:
la $a0, output
li $v0, 4
syscall
move $a0, $t0
li $v0, 1
syscall
la $a0, newline # How will the output change if newline is replaced by newspace defined as “ “?
li $v0, 4
syscall
Block3:
Do:
move $a0, $s4
li $v0, 1
syscall
la $a0, newline
li $v0, 4
syscall
slt $s1, $s4, $t0
addi $s4, $s4, 1
bgt $s1, $zero, Do # Why can’t we use “beq $s1, 1, Do “?
Block4:
Exit:
li $v0, 10
syscall
.data
input: .asciiz "Input a number: "
output: .asciiz "Let me count till "
newline: .asciiz "\n "
So I need help with identifying what the code does... I have the concept I just want o make sure Im properly figuring this out... So I have this so far:
move $t0, $v0 #Why do we need this? --- to store number in t0
la $a0, newline # How will the output change if newline is replaced by newspace defined as “ “?
--- load address of string to be printed into $a0 and adds the space if replaced by newspace
the last one I cant quite figure out...

MIPS: Printing Out a Histogram

I'm writing a MIPS program (assembly language) that takes in 10 integers and prints out a histogram represented by asterisks.
E.g.:
User input of 1, 2, 3, 4
Output:
*
**
***
****
I have most of this code written already in MIPS. The problem I am running into is printing out the correct length of asterisks. As of now it is simply printing out the a histogram all of the same length; the FIRST user inputed integer.
# program functionality:
.data
menu: .asciiz "\n1. New Histogram\n2. Print Histogram\n3. Quit\n"
prompt: .asciiz "\nEnter 10 numbers between 0 and 50 (inclusive):\n"
prompt1: .asciiz "\nEnter a valid number:\n"
asterisk: .asciiz "*"
space: .asciiz "\n"
array: .word 0:10
.text
main:
do:
jal print_menu
li $v0, 5
syscall
beq $v0, 1, new
beq $v0, 2, print
beq $v0, 3, quit
j do # end do
new:
jal new_user
j do
print:
jal print_user
j do
j quit
print_menu:
la $a0, menu
li $v0, 4
syscall
jr $ra
new_user:
la $a0, prompt
li $v0, 4
syscall
enter_loop:
la $t0, array
li $t1, 10
enter_loop_2:
la $a0, prompt1
li $v0, 4
syscall
li $v0, 5
syscall
sw $v0, ($t0)
addi $t1, $t1, -1
beqz $t1, end_loop_2
addi $t0, $t0, 4
j enter_loop_2
end_loop_2:
jr $ra
print_user:
la $t0, array
li $t1, 10
pLoop:
la $a0, space
li $v0, 4
syscall
asterisk_fun:
li $v0, 1
lw $a0, ($t0)
syscall
counter:
la $a0, asterisk
li $v0, 4
syscall
addi $a0, $a0, -1
beqz $a0, asterisk_end
j counter
asterisk_end:
jr $ra
addi $t1, $t1, -1
beqz $t1, endpLoop
addi $t0, $t0, 4
j pLoop
endpLoop:
jr $ra
quit:
li $v0, 10
syscall
The problems is that you are overwriting register $a0 in counter with the address of the asterisk, and you also used $a0 to count the number of items in that bucket.
Easy solution is to use other register (e.g. $a1) to count the number of items:
That would be:
#... your code
asterisk_fun:
li $v0, 1
lw $a1, ($t0) # Load number in $a1
move $a0, $a1 # move to $a0 just to print it
syscall
la $a0, asterisk
counter:
li $v0, 4
syscall
addi $a1, $a1, -1 # we use $a1 to keep the counter
beqz $a1, asterisk_end
j counter
asterisk_end:
# ... more of your code