2

I was able to (partly) successfully read in a file in MIPs. Below is my current code. In QtSpim, when I run it, I get a pointer to the file in $a1, but the last few characters of the file are repeated twice. The number of characters that is repeated changes depending on the file. From what I've seen, it seems to be linked to the number of new-line characters in the file unless the new-line chars are at the very end of the file (meaning, if there were 5 new-line characters, the last 5 characters of the file would appear duplicated at the end of the file read in), although I don't see any reason why this should be true. (FYI, this code is copied almost verbatim from here except it reads instead of writes)

.data
fin: .asciiz "c:/input.txt"
fBuffer: .space 1024
.text
main:
    jal  openFile
    jr   $ra

#returns: pointer to file's text in $a1
openFile:
    li   $v0, 13       # system call for open file 
    la   $a0, fin  #fin is the file name
    li   $a1, 0    # 0 means 'read'
    li   $a2, 0
    syscall            # open file
    move $s6, $v0      # save the file descriptor

    #read from file
    li   $v0, 14       # system call for read from file
    move $a0, $s6      # file descriptor 
    la   $a1, fBuffer   
    li   $a2, 1024     # hardcoded buffer length
    syscall            # read from file

    # Close the file 
    li   $v0, 16       # system call for close file
    move $a0, $s6      # file descriptor to close
    syscall            # close file
    jr $ra

1 Answers1

2

You can't know the last line was repeated with this code. The link you gave clearly says in the Result column for file read that $v0 contains the number of bytes read. But your code immediately clobbers $v0 to close the file.

If you change your code to print only the characters actually read, the appearance of repeated information ought to go away.

If you are using the print string syscall, then just add one byte to the buffer (to prevent overrun) and then write a null terminator after the characters read. Something like:

syscall            # (your code) read from file 
la $a0, fBuffer    # load 32-bit buffer address
add $a0, $a0, $v0  # calculate address of byte after file data 
sb $zero, 0($a0)   # set that byte to zero
Gene
  • 46,253
  • 4
  • 58
  • 96
  • Thanks so much. This did it. FYI, the second line of your code should be "la $a0, fBuffer" not "li", but that's just a simple typo. Am I doing something wrong that I need to manually add a null char to the end of the file? Why would it duplicate the end of the file? –  Apr 18 '14 at 03:36
  • 1
    @Cruzer Your file read is fine (unless it's longer than 1024 characters). You just need to convert the input to a string as expected by the print routine. You'd have to do exactly the same thing in C if you used `fread` to read the file and `puts` to print the string. The appearance of duplication is probably because the syscall used the memory just after your buffer for it's own buffering, leaving data behind after it was complete. Your print statement ran off the end of your buffer into the syscall area, and the repeated information was just a coincidence. It could have been any junk. – Gene Apr 18 '14 at 13:01