我将如何使用MIPS汇编语言逐行读取文件 [英] How would I read a file line by line using the MIPS assembly language

查看:78
本文介绍了我将如何使用MIPS汇编语言逐行读取文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为我的课程设计一个项目,该项目要求我逐行从文件中读取.我们的最终目标是使用MIPS语言制作MIPS汇编器,但是与此帖子相关的问题是我无法从文件中逐行读取.到目前为止,我已经创建了一种从文件中读取信息的机制.

I was working on a project for my class which requires me to read in from a file line by line. Our end goal is to make a MIPS assembler using the MIPS language, but the problem pertinent to this post is that I cannot read in line by line from the file. I have created this so far as a mechanism to read in information from the file.

.data
file_loc: .asciiz "test.asm" #note: when launching from commandline, test.asm should be within the same folder as Mars.jar
buffer: .space 1024 #buffer of 1024
new_line: .asciiz "\n"  #where would I actually use this?

#error strings
readErrorMsg: .asciiz "\nError in reading file\n"
openErrorMsg: .asciiz "\nError in opening file\n"

.text
main:
jal openFile
j endProgram

openFile:
#Open file for for reading purposes
li $v0, 13          #syscall 13 - open file
la $a0, file_loc        #passing in file name
li $a1, 0               #set to read mode
li $a2, 0               #mode is ignored
syscall
bltz $v0, openError     #if $v0 is less than 0, there is an error found
move $s0, $v0           #else save the file descriptor

#Read input from file
li $v0, 14          #syscall 14 - read filea
move $a0, $s0           #sets $a0 to file descriptor
la $a1, buffer          #stores read info into buffer
li $a2, 1024            #hardcoded size of buffer
syscall             
bltz $v0, readError     #if error it will go to read error

li $v0, 4
la $a0, buffer
syscall

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

openError:
la $a0, openErrorMsg
li $v0, 4
syscall
j endProgram

readError:
la $a0, readErrorMsg
li $v0, 4
syscall
j endProgram


endProgram:
li $v0, 10
syscall

问题是,读取文件将读取缓冲区(1024)而不是行中可以容纳的尽可能多的字节.

The problem is reading in a file will read in as many bytes that can be held within the buffer (1024), rather than the line.

例如,读取一个名为test.asm的文件,其中包含以下数据:

For example reading in a file named test.asm with the following data:

test abc abc abc

test2 1231 123 123

将产生以下输出:

test abc abc abc

test2 1231 123 123

我希望一次能读一行:

test abc abc abc

我知道减小缓冲区大小将有助于限制此信息,但是在输入行很长的情况下,可能会引起一些问题.我希望看看是否有人知道如何从缓冲区中读取一定量的内容,然后在新的行指示器处将其拆分(我很确定它的"\ n").

I know that reducing the buffer size will help limit this information, but in the case of a long line of input it may cause some problems. I was hoping to see if anyone knows how to read in a certain amount from the buffer and then split it at the new line indicator (I'm pretty sure its "\n").

任何帮助/提示将不胜感激!谢谢!

Any help/tips would be appreciated! Thanks!

推荐答案

像您所做的一样,读取大块当然是可能的.就最小化系统调用而言,这是有效的,但是代码编写起来有些繁琐.您将需要一个循环来遍历每个块以找到任何换行符,并需要一个缓冲区来存储不完整的行,这些行需要多次读取才能构建.

It's certainly possible to read large chunks like you're doing. This is efficient in terms of minimizing syscalls but the code is a bit fussy to write. You'd need a loop to walk over each chunk to locate any newlines and a buffer to store incomplete lines that require multiple reads to build.

一种易于编写的惰性方法是逐字节读取文件,这使换行检测变得轻松:

A lazy approach that's easier to code is to read the file byte by byte which makes newline detection effortless:

# if current byte is a newline, consume line
lb $s4 ($s1)  # load the current byte from the buffer
li $t0 10     # ASCII newline
beq $s4 $t0 consume_line

您可以使用 sbrk (系统调用9)为缓冲区分配更多的内存,以处理任意长的行,但是对于本示例,我将假定行的长度永远不超过1024字节.为了使示例保持最少,我将保留更好的错误处理,行消耗代码和模块化作为练习.

You could use sbrk (system call 9) to allocate more memory for the buffer to handle arbitrarily long lines, but for this example I'll assume lines are never longer than 1024 bytes. I leave better error handling, line consumption code and modularity as an exercise in the interest of keeping the example minimal.

您可以将其另存为 read_file_lines.s ,并使用 spim -f read_file_lines.s 运行,它将打印自己的源代码.

You can save this as read_file_lines.s, run with spim -f read_file_lines.s and it'll print its own source code.

.data  
fin: .asciiz "read_file_lines.s"
buffer: .space 1
line: .space 1024
.globl main
.text
main:
    la $s1 buffer
    la $s2 line
    li $s3 0      # current line length

    # open file
    li $v0 13     # syscall for open file
    la $a0 fin    # input file name
    li $a1 0      # read flag
    li $a2 0      # ignore mode 
    syscall       # open file 
    move $s0 $v0  # save the file descriptor 

read_loop:

    # read byte from file
    li $v0 14     # syscall for read file
    move $a0 $s0  # file descriptor 
    move $a1 $s1  # address of dest buffer
    li $a2 1      # buffer length
    syscall       # read byte from file

    # keep reading until bytes read <= 0
    blez $v0 read_done

    # naively handle exceeding line size by exiting
    slti $t0 $s3 1024
    beqz $t0 read_done

    # if current byte is a newline, consume line
    lb $s4 ($s1)
    li $t0 10
    beq $s4 $t0 consume_line

    # otherwise, append byte to line
    add $s5 $s3 $s2
    sb $s4 ($s5)

    # increment line length
    addi $s3 $s3 1

    b read_loop

consume_line:

    # null terminate line
    add $s5 $s3 $s2
    sb $zero ($s5)

    # reset bytes read
    li $s3 0

    # print line (or consume it some other way)
    move $a0 $s2
    li $v0 4
    syscall

    # print newline
    li $a0 10
    li $v0 11
    syscall

    b read_loop

read_done:

    # close file
    li $v0 16     # syscall for close file
    move $a0 $s0  # file descriptor to close
    syscall       # close file

    # exit the program
    li $v0 10
    syscall

这篇关于我将如何使用MIPS汇编语言逐行读取文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆