bI'm not so sure why it's not reading the input and deciding to repeat or end.. Here is my code, help would be appreciated!
.data
again:
.asciiz "Again (y or n)? "
answer:
.asciiz " "
.text
.globl main
main:
li $v0, 4
la $a0, again
syscall
la $s4, answer
jal get
beq $v0, 'y', main
beq $v0, 'Y', main
li $v0, 10
syscall
get:
li $v0, 12
li $a1, 2
syscall
jr $ra
Consider this:
.data
again:
.asciiz "Again (y or n)? "
answer:
.space 256
.text
.globl main
main:
li $v0, 4
la $a0, again
syscall
la $a0, answer
li $a1, 3
li $v0, 8
syscall
lb $t4, 0($a0)
beq $t4, 'y', main
beq $t4, 'Y', main
li $v0, 10
syscall
Firstly, in your code, you seem to misunderstand the way the syscalls work and how they ought to interact with functions (some docs here). Because your get routine basically just called a syscall, I took it out as adding a routine for something that basic is probably adding complexity rather than reducing it.
Next, the main problem of your code was a misunderstanding of the way input buffering works. In your code, you allocated exactly 2 bytes of space for answer, and then use syscalls to get no more than 2 bytes at a time. This will not work for stdin, because on most systems, stdin is line buffered, meaning that the user must press ENTER in order to flush the stream. This means that when the user types 'y', a syscall actually returns "y\n\0".
To fix this I expanded the syscall to read 3 characters and answer to store up to 256. Expanding this to be safe for any size is an excersize left to the reader.
Related
I am new to MIPS and I wrote a basic format of what I think the code from the C file I wrote is the equivalent to of the MIPS.
My assignment is to convert the following C file which I wrote into a direct translation of what the MIPS is supposed to be. My current C code is :
#include <stdio.h>
int d2b(int d)
{
if(d == 0)
{
return;
}
else
{
return (d %2 + 10 * d2b(d/2));
}
}
int main()
{
int d = 99;
int b;
b = d2b(d);
printf("Input => %d \n", d);
printf("Output => %d ", b);
return;
}
So far I have the following :
.data
msg1 .asciiz “Number is “
msg2 .asciiz “\nConverted to \n“
.text
.globl main
main:
li $v0, 4
la $a0, msg1
syscall
li $v0, 5 #Exit syscall
syscall
add $a0, $v0, $zero
jal fact
add $a0, $v0, $zero
li $v0, 1
syscall
li $v0, 10
la $a0, msg2
syscall
fact:
li $t0 0 #load 0
beq $a0, $t0, skip #test n
li $v0 0
jr $ra
skip:
subu $sp, $sp, 32
sw $ra 20($sp)
sw $fp, 16($sp)
addiu $fp, $sp, 28
sw $a0, 0($fp) #save n
li $t1 2 #load 2
divu $a0 $t1 #n / 2
mfhi $t2 #remainder
mflo $t3 #quotient
move $a0, $t3 #n = quotient
addi $v0, $a1, 10
jal fact
lw $a0, 0($fp) #restore n
multu $v0, $a0
lw $ra, 20($sp)
lw $fp, 16($sp)
addiu $sp, $sp, 32
jr $ra
My main problem is not knowing how to use syscall and not really understand a recursive function in MIPS. Please point out my mistakes and errors!
your MIPS syscalls are in this section
li $v0, 4
la $a0, msg1
syscall
li $v0, 5 #Exit syscall
syscall
add $a0, $v0, $zero
jal fact
add $a0, $v0, $zero
li $v0, 1
syscall
li $v0, 10
la $a0, msg2
syscall
They are commented incorrectly
In a MIPS syscall $v0 holds the "syscall function" or in English, the service you want the operating system to perform. There's a table of them here.
$a0 will hold the first parameter passed to the call. To set this parameter, one technique is to add the input value to zero storing the result into $a0 That's why you have so many lines like this
add $a0, $v0, $zero # this adds $v0 to the number zero and storing in $a0
Finally, the syscalls you are using are (4 => print String, 5 => read integer, 1 => print integer, and 10 => exit)
So a properly commented example of your code would be
la $a0, msg1 # load string as parameter
li $v0, 4 # load operation "print string"
syscall # request "print string" for msg1
li $v0, 5 # load operation "read integer"
syscall # request "read integer"
add $a0, $v0, $zero # load the read integer into $a0
jal fact
add $a0, $v0, $zero # load the value of $v0 into $a0
li $v0, 1 # load operation "print integer"
syscall # request "print integer"
As you can see, my confusion comes not from your ability to use syscalls, but from your description of what you think you are using the syscalls to do.
You state you want to print a binary number like 01001010 from a decimal input. This typically involves breaking the decimal number down, in a loop, printing out a zero or one in each of the binary number places. As this would require a loop for each placeholder in the binary number, it doesn't seem that a single call to "print integer" would be possible (unless the input was limited to only the decimal '1' and '0', or the input is limited to such a small number that it's binary representation, represented in decimal format is less than max_int).
So for an input of 5, the desired output would be 101, and that would be 3 calls to print, in the order of '1', '0', '1'. I believe this approach of printing the digits in a loop will give you greater success, and will permit you to print every positive decimal number inputted.
In short, I think your command of syscall is fine, but you're still struggling with how to do loops and solve problems in assembly. Try to figure out how you would determine the digits in the needed order by hand, using a pencil and paper, and then attempt to code that into your program.
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
Alright so i'm using a premade PRNG (LFSR_Random) and calling it to get a random number, i'm then trying to put this number into a register so I can compare it to my guesses and get responses.
I'm having major issues calling this generator with JAL and getting it to where I want to store it, I think I have the correct logic in here but i've been getting non responses not even returning the strings just asking for ("Enter Number: ") again, so either the value in the register is completely off or its not comparing correctly.
And if need be I can upload the entire other set of functions(?) that utilize the PRNG for reference.
Just ask.
.data
start: .asciiz "Guess Game(1-100)"
entnum: .asciiz "\n Enter number: "
toolow: .asciiz "\n Too Low"
toohigh: .asciiz "\n Too High"
correct: .asciiz "\n Correct"
.text
.globl main
main:
li $v0, 4
la $a0, start #prints out the start string
syscall
li $v0, 0 #initiliaze register $v0
move $s1, $v0 #move the random number into $s0
jal LFSR_Random #call the random number generator
#LSFR_Random returns an upper
#32-bit unsigned number
#in $v0
#and a lower 32-bit number in $v1
move $s2, $s1 #moves rn into s2
remu $t0, $s2, 100 #divides so i can get it between 1-99
addi $t0, $10, 1 #now between 1-100
loop1:
li $v0, 4
la $a0, entnum #print query
syscall
li $v0, 5 #enter query
syscall
blt $v0, $t0, toolowc #calls if the guess is too low
bgt $v0, $t0, toohighc #calls if the guess is too high
beq $v0, $t0, correctc #calls if the guess is correct
#ending the loop and program.
toolowc:
la $a0, toolow #called from blt, prints response
syscall
j loop1 #resets to the loop
toohighc:
la $a0, toohigh #called from bgt, prints response
syscall
j loop1 #resets to the loop
correctc:
la $a0, correct #called from beq, prints response
syscall
j endcall #calls the ending call, ending the program
endcall:
li $v0, 10
syscall
########################
I am currently using MIPS Assembly. I have recently learned how to do both macros and arrays (of a sort), so I promptly wrote a fairly simple program to test them out. However, between getting the data and displaying it again, I wish to output a new message. For some reason, my program doesn't appear to do this, even though when running through it step by step it DOES, in fact, go through those lines - it just simply doesn't have any output. Is there any particular reason in MIPS Assembly why this isn't working, or is it a glitch in the MARS assembler?
.data
testlist: .word 50
request: .asciiz "Enter pi up to 50 digits: 3."
out: .asciiz "\nPi: 3."
.text
.macro arraygetword(%initaddress,%offset,%storeto)
la $a1,%initaddress
mul $a0,%offset,4
add $a0,$a0,$a1
lw %storeto,($a0)
.end_macro
.macro arraysetword(%initaddress,%offset,%value)
la $a1,%initaddress
mul $a0,%offset,4
add $a0,$a0,$a1
sw %value,($a0)
.end_macro
.macro arraygetbyte(%initaddress,%offset,%storeto)
la $a1,%initaddress
add $a0,%offset,$a1
lw %storeto,($a0)
.end_macro
.macro arraysetbyte(%initaddress,%offset,%value)
la $a1,%initaddress
add $a0,%offset,$a1
sw %value,($a0)
.end_macro
main:
la $a0,request
li $v0,4
syscall
li $t0,0
li $t1,50
forloop:
li $v0,12
syscall
arraysetword(testlist,$t0,$v0)# testlist[$t0]=$v0
addi $t0,$t0,1
blt $t0,$t1,forloop
li $t0,0
li $t1,50
la $a0,out# This is the part not working.
li $v0,4# Why doth this not output anything?
syscall# I need some sort of line break. It's awkward otherwise.
output:
arraygetword(testlist,$t0,$a0)# $a0=testlist[$t0]
li $v0,11
syscall
addi $t0,$t0,1
blt $t0,$t1,output
li $v0,10
syscall
testlist: .word 50 does not allocate 50 words, it allocates a single word with value 50. As such, your program is overwriting the memory after it, which contains your strings to print. Of course by that time you have already printed the request so that is not affected.
I am trying to store a dynamic array into a program using a stack, by first reading an input n and then creating a stack with [n] inputs. However, when I try to store word, it creates an error that I don't understand.
.data
ask_for_size: .asciiz "\nInsert the array size\n"
ask_for_int: .asciiz "\nInput number\n"
input: .space 16
.text
Main:
li $v0,4
la $a0,ask_for_size
syscall
li $v0,5
la $a0,input
syscall
add $t0,$v0,$zero
li $sp,0x00001000 #stack pointer
li $s0,0x00001000 #base pointer
la $a0,ask_for_int
Loop1:
li $v0,4
syscall
li $v0,5
syscall
sw $v0,0($sp)
addi $sp,$sp,-4
addi $t0,$t0,-1
bne $t0,$zero,Loop1
j Loop2
Loop2:
Shouldn't you add -4 to $sp before you sw $v0 into it?
addi $sp,$sp,-4
sw $v0,0($sp)
It seems to me that at this time you're overwriting past the end of $sp allocated for your process.
Also you load $a0 only once. Are you sure it does not get modified? Otherwise, maybe that would work better?
Loop1:
li $v0,4
la $a0,ask_for_int
syscall
...