File 如何使用MIPS汇编语言逐行读取文件
我在为我的班级做一个项目,要求我逐行阅读文件。我们的最终目标是使用MIPS语言制作一个MIPS汇编程序,但与本文相关的问题是我无法逐行读取文件。到目前为止,我已经创建了一个从文件中读取信息的机制File 如何使用MIPS汇编语言逐行读取文件,file,io,mips,File,Io,Mips,我在为我的班级做一个项目,要求我逐行阅读文件。我们的最终目标是使用MIPS语言制作一个MIPS汇编程序,但与本文相关的问题是我无法逐行读取文件。到目前为止,我已经创建了一个从文件中读取信息的机制 .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 #bu
.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)中可容纳的字节数,而不是行数
例如,在名为test.asm的文件中读取以下数据:
test abc abc abc
test2 1231 123 123
将产生以下输出:
test abc abc abc
test2 1231 123 123
我希望每次只读一行:
test abc abc abc
我知道减小缓冲区大小将有助于限制此信息,但在输入行较长的情况下,可能会导致一些问题。我希望知道是否有人知道如何从缓冲区读取一定数量的数据,然后在新行指示器处拆分它(我很确定它的“\n”)
如有任何帮助/提示,将不胜感激!谢谢 当然可以像你现在这样读大块的内容。这在最小化系统调用方面是有效的,但是代码编写起来有点繁琐。您需要一个循环遍历每个块来定位任何换行符,并需要一个缓冲区来存储需要多次读取才能生成的不完整行 一种更容易编码的惰性方法是逐字节读取文件,这使得新行检测变得轻松:
# 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字节。为了使示例最小化,我将更好的错误处理、行消耗代码和模块化留作练习
您可以将其另存为read_file_lines.s
,使用spim-f read_file_lines.s
运行,它将打印自己的源代码
.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
.data
fin:.asciiz“读取文件行.s”
缓冲区:。空间1
行:。空格1024
格洛博梅因酒店
.文本
主要内容:
la$s1缓冲区
la$s2线路
li$s3 0#当前线路长度
#打开文件
li$v0 13#打开文件的系统调用
la$a0 fin#输入文件名
li$a1 0#读取标志
li$a2 0#忽略模式
系统调用#打开文件
移动$s0$v0#保存文件描述符
读循环:
#从文件中读取字节
li$v0 14#读取文件的系统调用
移动$a0$s0#文件描述符
移动$a1$s1#目的地缓冲区地址
li$a2 1#缓冲区长度
syscall#从文件中读取字节
#继续读取,直到字节读取为止,这样一次读取1024(或任何数字)字节,然后编写一个函数,返回缓冲区中的下一行。这方面有什么进展吗?