i have a problems in MIPS, i read a line in file then split the string to an array of integer values , finally i get an array with those number 100,5,20,-8,2. i want to print the value a[4]=2 to a file.I read a link that give me an instruction about how we can access the value 2 at position 4 http://people.cs.pitt.edu/~xujie/cs447/AccessingArray.htm . i try my code
output: .asciiz "output.txt"
#open file
li $v0, 13
la $a0,output
li $a1, 1
li $a2, 0
#accessing array
la $t3,buffer //access my array name buffer
li $t5,4 //$t5=4
add $t5,$t5,$t5
add $t5,$t5,$t5
add $t1,$t5,$t3
//write to file
li $v0, 15
move $a0, $s6
move $a1, $t1
li $a2, 4 //buffer length
syscall
//close
li $v0, 16
move $a0, $s6
syscall
But when i check my file ,nothing happend in my file. What happended ? Thanks for your help
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
First of all, I have already checked related questions to this one, yet I am still not able to overcome the problem I have with this program.
What I am trying to do is, basically, take a byte[] input and duplicate it to another byte[], and print the duplicate array. My code is as above:
.data
hello: .asciiz "hello"
inp: .byte 5
dup: .byte 5
.text
main:
la $a0, inp #get input
li $v0, 8
syscall
la $s0, dup #load arrays on s0 and s1
la $s1, inp
li $t0, 0 #instantiate offsets as 0
li $t2, 0
Load:
lb $t1, 0($s1) #load first byte
sub $t1, $t1, 48 #test if it is <0
bltz, $t1, exit #if so go to exit
add $t1, $t1, 48
sb $t1, 0($s0) #else save the byte
add $s1, $s1, 1 #increment offsets
add $s0, $s0, 1
j Load
la $a0, hello
li $v0, 4
syscall
exit:
li $t1, 0
add $s0, $s0, 1
sb $t1, 0($s0) #add null to the end of dup
la $a0, dup
li $v0, 4
syscall
jr $ra
I am new to MIPS and, I am not able to recognize what the problem is.
By the way, I am passing 123 as an input and I am getting countless of 1s as output, which tells me that I am stuck in the loop and never getting any further in $s1 (inp).
There are a couple of problems with your code:
First, .byte 5 doesn't reserve space for 5 bytes, it declares a single byte with the value 5. If you want 5 bytes you should say .space 5 (the bytes will be initialized with the value 0 IIRC).
Second, syscall 8 takes one more argument; $a1 = maximum number of characters to read, which you haven't specified. If you have room for 5 bytes in your buffer you should set $a1 to 5. Note that "maximum number of characters to read" actually means "maximum number of characters to read including the terminating null-character".
I'm trying to create a file named "exit.txt", and write some data on it. I have tried different flags and modes, but that doesn't seem to work. This is the code I'm using:
str_exit: .asciiz "/home/LinuxPc/Desktop/exit.txt"
file_write:
li $v0, 13
la $a0, str_exit
li $a1, 1
la $a2, 0
syscall
Is there any way to make it work ??
Thanks !!
In addition to the answer of gusbro (open file stream before writing) it might help to set the flags and mode for the open file call as follows:
li $a1, 0x41
li $a2, 0x1FF
This sets the flag to the hex value 0x41 which tells the call to first create the file. While the mode is set to hex value 0x1FF which is converted to the binary value
0000 0000 0001 1111 1111 that sets the file permission for:
(...)0 111(n) 111(g) 111(others).
You put the code to open a file in write mode, but you didn't write anything into the file.
Here goes an example of how to open/write/close a file:
.data
str_exit: .asciiz "test.txt"
str_data: .asciiz "This is a test!"
str_data_end:
.text
file_open:
li $v0, 13
la $a0, str_exit
li $a1, 1
li $a2, 0
syscall # File descriptor gets returned in $v0
file_write:
move $a0, $v0 # Syscall 15 requieres file descriptor in $a0
li $v0, 15
la $a1, str_data
la $a2, str_data_end
la $a3, str_data
subu $a2, $a2, $a3 # computes the length of the string, this is really a constant
syscall
file_close:
li $v0, 16 # $a0 already has the file descriptor
syscall
.data
array: .word 0:5
prompt1: .asciiz "enter number: "
newline: .asciiz "\n"
.text
add $t2,$zero,$zero # initializes counter to 0
la $s0, array # stores the beginning of array into $s0
secretcode:
li $v0, 4 # prints "enter number: "
la $a0, prompt1
syscall
li $v0, 5 # reads in user input
syscall
sw $v0, ($s0) # saves user input into address at $s0
addi $s0, $s0, 4 # increments address at $s0 by 4 bytes
addi $t2, $t2, 1 # increments counter by 1
bne $t2, 5, secretcode # stops loop when loop executes 5 times
printsecretcode:
lw $a0, ($s0) # print first element
li $v0, 1
syscall
li $v0, 10 # system code halt
syscall
The program is supposed to store 5 user inputted numbers into an array. I tried to print the first value but it comes up as a large number which I assume is an address. How would I print the actual value of the number so that I know it saved correctly?
By the time you reach your printing code $s0 contains the address array + 4*5, so what you end up printing is the 32-bit number formed by the first four characters of the "enter number: " string.
To fix this, add an la $s0, array before you try to print the first element.