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
Related
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.
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.
My code comes up with Unsupported R-Type, how do I make it subtract correctly. Tried changing other details within.... Already tried using subu...............................................................................................
.data
str: .asciiz "\nHello World!\n"
# You can change what is between the quotes if you like
.text
.globl main
main:
# Do the addition
# For this, we first need to put the values
# to add into registers ($t0 and $t1)
li $t0, 30 # You can change the 10
li $t1, 20 # You can change the 20
# Now we can add the values in $t0
# and $t1, putting the result in special register $a0
sub $a0, $t0, $t1
# Set up for printing the value in $a0.
# A 1 in $v0 means we want to print an int
li $v0, 1
# The system call looks at what is in $v0
# and $a0, and knows to print what is in $a0
syscall
# Now we want to print Hello World
# So we load the (address of the) string into $a0
la $a0, str
# And put a 4 in $v0 to mean print a string
li $v0, 4
# And just like before syscall looks at
# $v0 and $a0 and knows to print the string
syscall
# Nicely end the program
li $v0, 0
jr $ra
Your program runs fine in the mars and spim simulators except for program termination. These simulators don't set up $ra, so it's zero. So, at the end, you're returning to something that may have semi-random instructions, including an illegal one. Thus, it's not your sub at all that is the problem. It's what happens later.
Change:
# Nicely end the program
li $v0, 0
jr $ra
Into:
# Nicely end the program
li $v0, 10
syscall
How could i read values so i can store them in memory after? I need to get the user to input values and then press enter so i can get those values and work with them.
Thank you
You should use service 5 to read an integer, 6 to read a float, 7 for a double and service 8 to read a string. See MARS reference for syscall services provided.
Here goes an example that reads an integer and a string from console and holds the results in variables number and buffer:
.data
number: .word 0
buffer: .space 80
.text
li $v0, 5 # service 5 reads integer from console
syscall
sw $v0, number # Store read integer into number
li $v0, 8 # service 8 reads a string
la $a0, buffer
li $a1, 80 # buffer size
syscall # input text will be stored in buffer
li $v0, 7 # service 7 reads double
syscall # $f0-$f1 contains the double read
mov.d $f2, $f0
syscall # read another double
div.d $f12, $f2, $f0 # Divide the first double by the second double
li $v0, 3
syscall # Print result of division
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"