opening binary file for reading - mips

I'm trying to open binary file for reading in mars mips simulator:
.data
file: .asciiz "o.bmp"
.text
li $v0, 13
la $a0, file
li $a1, 0
li $a2, 0
syscall #file descriptor of oepened file in v0
beq $v0, -1, end #my program every time jumps to end so sth is wrong

solution:
file mars.jar (or other name of mars program) must be in the same directory with file "o.bmp"

Related

MIPS Assembly File Writing

I am trying to write to a file in MIPS assembly and it seems that I cannot get it to work. The code is straightforward, but the $v0 register returns -1 no matter what I type. I have tried other people's code and still end up getting the same results.
The code:
filename: .asciiz "file.txt"
buffer: .asciiz "hello textual world"
.text
open_file:
li $v0, 13 # open file
la $a0, filename # file name
li $a1, 1 # write flag
li $a2, 0 # ignore mode
syscall
jal print
write_to_file:
move $a0, $v0 # descriptor
li $v0, 15 # write to file
la $a1, buffer # buffer
li $a2, 20 # max chars to write
syscall
jal print
close_file:
li $v0, 16 # close
# move $a0, $v0 # descriptor
syscall
jal print
li $v0, 10 # exit program
syscall
print:
move $a0, $v0
li $v0, 1
syscall # print v0
li $v0, 11
li $a0, '\n'
syscall # print '\n'
jr $ra
The output:
-1
-1
16
-- program is finished running --
A Screenshot of the Mars dir. Note: I know that the dir contains "FILES.txt" rather than the "file.txt" one. However, I am trying to create a new file.
EDIT:
After some time I ran the program and solved the issue. For some reason, the first syscall did not return -1 when I ran it today, but the problem was that in "jal print", $v0 changed its value, which means that the line that follows it, first line of write_to_file label, loads an incorrect descriptor to $a0. Another potential problem is that I put 20 characters to print instead of 19.
Long story short, I've saved the file descriptor in $s0 and put 19 characters to be written and now the program works.

Opening file always returns "-1" in QtSpim

I'm working on a university project where we have to write Data to a file via MIPS. I get everything to run on MARS, but on QtSpim, just opening a file always returns an error:
.data
file_name: .asciiz "test.pgm"
#
# main
#
.text
.globl main
main:
# Open File in write mode
li $v0, 13 # $v0 = 13, option for opening file
la $a0, file_name # $a0 = &file_name
li $a1, 1 # $a1 = 1, write-flag
li $a2, 0 # $a2 = 0, mode is ignored
syscall # open File, save descriptor to $v0
jr $ra # return
When I run this in QtSpim step by step I get a -1 in $v0 after the syscall.
Any ideas, why QtSpim can't run this? I'm on Windows 10, QtSpim version 9.1.17, although the same version on LinuxMint 18 has the same problem. Any help appreciated, for now I'll just run everything on MARS, but we have to hand in something that works on QtSpim.
UPDATE
It seems to work when I use absolute paths, but the file must exist in order to open it in write mode. Is there a way to create the file if it doesn't exist?
Relative paths in QtSpim are based on the directory it is executed from, which may be a different one than the location of your code or the image.
Well, after a lot of trial and error, it seems to work when I open the file with Flag 0x41 and mode 0x1FF.
If I understand it correctly, 0x41 is for write with create and 0x1FF for the correct permissions.
main:
# Open File in write mode
li $v0, 13 # $v0 = 13, option for opening file
la $a0, file_name # $a0 = &file_name
li $a1, 0x41 # $a1 = 0x41, write-flag with create
li $a2, 0x1FF # $a2 = 0, permissions
syscall # open File, save descriptor to $v0
jr $ra # return
And absolute paths, apparently QtSpim can't even write into it's own directory when started as admin, so really only absolute paths work.

Assembly MIPS - Create a file, specific extension

I am coding a program in asm, I know a bit, but no expert. I am using Mars emulator. The part I do not understand is how does one create a file and make it have an specific extension like, file.vig? What I want is to create a file, give a name I want, write to it. None of this worked so far. I have the rest of the program working, but not this file creation and modification while in run time of Mars.
res points to a string
FileName points to a string like: file.vig
li $v0, 13 # system call for open file
la $a0, FileName # output file name
li $a1, 577 # Open for writing (flags are 0: read, 1: write)
li $a2, 0x1ff # was recommended for file permissions
syscall # open a file (file descriptor returned in $v0)
move $s6, $v0 # save the file descriptor
# Write to file just opened
li $v0, 15 # system call for write to file
move $a0, $s6 # file descriptor
la $a1, res # address of buffer from which to write
li $a2, 15 # hardcoded buffer length
syscall
move $a0, $s6
li $v0, 16 # close
syscall
li $v0, 10
syscall
You didn't check the return value from your open syscall. It was returning -1 because you were loading $a1 with 577 and not 1 [it's not quite like libc and is finicky about this value].
Here's your program, slightly adjusted to demo this and retry the open with the correct options [please pardon the gratuitous style cleanup]:
.data
FileName: .asciiz "file.vig"
bad_msg: .asciiz "open syscall failed\n"
ok_msg: .asciiz "open was okay\n"
res: .byte 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
.text
.globl main
main:
li $a1,577 # Open for writing (flags are 0: read, 1: write)
li $a2,0x1ff # was recommended for file permissions
main_retry:
li $v0,13 # system call for open file
la $a0,FileName # output file name
syscall # open a file (descriptor returned in $v0)
move $s6,$v0 # save the file descriptor
bltz $s6,main_fail # did open fail? fly if yes
la $a0,ok_msg
li $v0,4
syscall
# Write to file just opened
li $v0,15 # system call for write to file
move $a0,$s6 # file descriptor
la $a1,res # address of buffer from which to write
li $a2,15 # hardcoded buffer length
syscall
move $a0,$s6
li $v0,16 # close
syscall
main_exit:
li $v0,10
syscall
main_fail:
la $a0,bad_msg
li $v0,4
syscall
li $a1,1 # correct write mode (O_WRONLY)
li $a2,0 # file permissions are ignored by mars
j main_retry

In MIPS, how to use syscall 14 to read through a long file?

I am currently working on a project (using MARS) where I need to read a multi-line file using syscall 14. I have a set buffer-length that I am using for the syscall that is 80-bytes long. I have set up my loop within a _readLine function so that the contents of the buffer should be printed to the console with each iteration. This is how I realized that my loop only reads the first 80-bytes of a file, and nothing more.
I've been scouring the internet trying to find a hint on why I can't read the next 80-bytes of the file. I thought it might have something to do with the file descriptor, but when I tried incrementing it, nothing changed, and it was still only outputting the first 80-bytes of the file with syscall 14.
Can someone please help me figure out what is wrong, or give me an idea as how to point to the next 80 bytes of my file? My code is below (fileBuff holds the address of a user-inputted file name, and _printBuffer is a function I use later in my program but you can ignore).
main:
# Open file for reading
addi $v0, $zero, 13
la $a0, fileBuff
add $a1, $zero, $zero # pass in flags
add $a2, $zero, $zero # pass in mode
syscall # open a file (file descriptor returned in $v0)
add $s6, $zero, $v0 # store descriptor in $a0
jal _readLine # call _readFile function
jal _printBuffer
addi $v0, $zero, 10 # prepare to exit the program
syscall # exit
_readLine:
readLoop:
add $a0, $zero, $s6 # setup file descriptor
la $a1, buffer # address of buffer
addi $a2, $zero, 80 # read 80 bytes
addi $v0, $zero, 14 # read from the file (descriptor already in $a0, buffer address in $a1, buffer length in $a2)
syscall # write to the file
beq $v0, $zero, doneReading
slt $t0, $v0, $zero # if end of file, then close file
beq $t0, 1, doneReading # if error, then close file
la $t0, buffer # load buffer address into $t0
add $s6, $zero, $v0 # save file length in $s0
add $s6, $s6, $t0 # change descriptor to where last left off in the file
#### remove... eventually
addi $v0, $zero, 4
la $a0, buffer
syscall
####
j readLoop
doneReading:
addi $v0, $zero, 16 # syscall to close the file
add $a0, $zero, $s6 # file descriptor to close
syscall # close the file
jr $ra
Syscall 14 reads in a continuous string.
When you tell it to read 80-bytes, it will read 80 bytes.
When you call it again (without closing it), it will read the next 80 bytes and so on.
So I suggest you move this block of code:
addi $v0, $zero, 16 # syscall to close the file
add $a0, $zero, $s6 # file descriptor to close
syscall # close the file
into your main block right before the system exit call.

MIPS: is it possible to overwrite certain words of a file?

Is it possible to overwrite a file using MIPS?
I have a file and, under certain conditions (i.e. a user decide to update his personal data or delete completely) I need to delete/overwrite some words or row of the text file I have.
I tried this thing:
I already know how to find which word I would like to replace and, with a store byte i write on a buffer the "new" word.
Then I should save it on file. And that's where my problems begin since, using flag 1 (on syscall 13) overwrites the whole file and flag 9 doesn't apply any change. Here's my code. What am I doing wrong?
loop:
la $t6, empty_space
sb $t6, buffer($s7)
beq $s7, $t5, save_on_file
subi $s7, $s7, 1
j loop
save_on_file:
#open file
li $v0, 13
la $a0, file_out
li $a1, 1
li $a2, 0
syscall
move $s6, $v0
#write on file
li $v0, 15
move $a0, $s6
la $a1, buffer
move $a2, $s7
syscall
#close
li $v0, 16
move $a0, $s6
syscall
j menu