Create and write to file on MIPS - file

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

Related

C to MIPS Decimal to Binary Converter Using Recursion

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.

How can we accessing array data in MIPS

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

Reading and Printing User Entered MIPS Array

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

Assembly - Copying an array of bytes - MIPS

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".

MIPS: Storing integer input into memory using sw causes address out of range error

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
...

Resources