从 MIPS 程序集中的用户输入读取文件名

发布于 2024-08-27 20:17:37 字数 4017 浏览 8 评论 0原文

我正在编写一个 MIPS 汇编代码,它将询问用户文件名,并生成一些有关文件内容的统计信息。

但是,当我从一开始就将文件名硬编码到变量中时,它工作得很好,但是当我要求用户输入文件名时,它不起作用。

经过一些调试,我发现该程序在内存中用户输入的末尾添加了 0x00 字符和 0x0a 字符(检查 asciitable.com),这就是它不根据用户输入打开文件的原因。

任何人都知道如何摆脱这些额外的字符,或者如何在从用户那里获取文件名后打开文件?

这是我的完整代码(除了用户事物的文件名之外,它工作正常,任何人都可以自由地将它用于他/她想要的任何目的):

        .data
fin:   .ascii ""      # filename for input
msg0:   .asciiz "aaaa"
msg1:   .asciiz "Please enter the input file name:"
msg2:   .asciiz "Number of Uppercase Char: "
msg3:   .asciiz "Number of Lowercase Char: "
msg4:   .asciiz "Number of Decimal Char:   "
msg5:   .asciiz "Number of Words:          "
nline:  .asciiz "\n"
buffer: .asciiz ""
        .text

#-----------------------
    li $v0, 4
    la $a0, msg1
    syscall

    li $v0, 8
    la $a0, fin
    li $a1, 21
    syscall

    jal fileRead            #read from file

    move $s1, $v0           #$t0 = total number of bytes

    li $t0, 0   # Loop counter
    li $t1, 0   # Uppercase counter
    li $t2, 0   # Lowercase counter
    li $t3, 0   # Decimal counter
    li $t4, 0   # Words counter

loop:
    bge $t0, $s1, end           #if end of file reached OR if there is an error in the file
    lb $t5, buffer($t0)         #load next byte from file

    jal checkUpper              #check for upper case
    jal checkLower              #check for lower case
    jal checkDecimal            #check for decimal
    jal checkWord               #check for words


    addi $t0, $t0, 1            #increment loop counter

j loop

end:

    jal output
    jal fileClose

    li $v0, 10
    syscall







fileRead:
    # Open file for reading
    li   $v0, 13       # system call for open file
    la   $a0, fin      # input file name
    li   $a1, 0        # flag for reading
    li   $a2, 0        # mode is ignored
    syscall            # open a file 
    move $s0, $v0      # save the file descriptor 

    # reading from file just opened
    li   $v0, 14       # system call for reading from file
    move $a0, $s0      # file descriptor 
    la   $a1, buffer   # address of buffer from which to read
    li   $a2, 100000   # hardcoded buffer length
    syscall            # read from file

jr $ra

output:
    li $v0, 4
    la $a0, msg2
    syscall

    li $v0, 1
    move $a0, $t1
    syscall

    li $v0, 4
    la $a0, nline
    syscall

    li $v0, 4
    la $a0, msg3
    syscall

    li $v0, 1
    move $a0, $t2
    syscall

    li $v0, 4
    la $a0, nline
    syscall

    li $v0, 4
    la $a0, msg4
    syscall

    li $v0, 1
    move $a0, $t3
    syscall

    li $v0, 4
    la $a0, nline
    syscall

    li $v0, 4
    la $a0, msg5
    syscall

    addi $t4, $t4, 1
    li $v0, 1
    move $a0, $t4
    syscall

jr $ra

checkUpper:
    blt $t5, 0x41, L1           #branch if less than 'A'
    bgt $t5, 0x5a, L1           #branch if greater than 'Z'
    addi $t1, $t1, 1            #increment Uppercase counter

    L1:
jr $ra

checkLower:
    blt $t5, 0x61, L2           #branch if less than 'a'
    bgt $t5, 0x7a, L2           #branch if greater than 'z'
    addi $t2, $t2, 1            #increment Lowercase counter

    L2:
jr $ra

checkDecimal:
    blt $t5, 0x30, L3           #branch if less than '0'
    bgt $t5, 0x39, L3           #branch if greater than '9'
    addi $t3, $t3, 1            #increment Decimal counter

    L3:
jr $ra

checkWord:
    bne $t5, 0x20, L4           #branch if 'space'
    addi $t4, $t4, 1            #increment words counter

    L4:
jr $ra

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

注意:我正在使用 MARS Simulator,如果这有任何不同

更新: 我通过编写并调用以下过程解决了该问题: <代码>

nameClean:
    li $t0, 0       #loop counter
    li $t1, 21      #loop end
clean:
    beq $t0, $t1, L5
    lb $t3, fin($t0)
    bne $t3, 0x0a, L6
    sb $zero, fin($t0)
    L6:
    addi $t0, $t0, 1
j clean
L5:
jr $ra

I'm writing a MIPS assembly code that will ask the user for the file name and it will produce some statistics about the content of the file.

However, when I hard code the file name into a variable from the beginning it works just fine, but when I ask the user to input the file name it does not work.

after some debugging, I have discovered that the program adds 0x00 char and 0x0a char (check asciitable.com) at the end of user input in the memory and that's why it does not open the file based on the user input.

anyone has any idea about how to get rid of those extra chars, or how to open the file after getting its name from the user??

here is my complete code (it is working fine except for the file name from user thing, and anybody is free to use it for any purpose he/she wants to):

        .data
fin:   .ascii ""      # filename for input
msg0:   .asciiz "aaaa"
msg1:   .asciiz "Please enter the input file name:"
msg2:   .asciiz "Number of Uppercase Char: "
msg3:   .asciiz "Number of Lowercase Char: "
msg4:   .asciiz "Number of Decimal Char:   "
msg5:   .asciiz "Number of Words:          "
nline:  .asciiz "\n"
buffer: .asciiz ""
        .text

#-----------------------
    li $v0, 4
    la $a0, msg1
    syscall

    li $v0, 8
    la $a0, fin
    li $a1, 21
    syscall

    jal fileRead            #read from file

    move $s1, $v0           #$t0 = total number of bytes

    li $t0, 0   # Loop counter
    li $t1, 0   # Uppercase counter
    li $t2, 0   # Lowercase counter
    li $t3, 0   # Decimal counter
    li $t4, 0   # Words counter

loop:
    bge $t0, $s1, end           #if end of file reached OR if there is an error in the file
    lb $t5, buffer($t0)         #load next byte from file

    jal checkUpper              #check for upper case
    jal checkLower              #check for lower case
    jal checkDecimal            #check for decimal
    jal checkWord               #check for words


    addi $t0, $t0, 1            #increment loop counter

j loop

end:

    jal output
    jal fileClose

    li $v0, 10
    syscall







fileRead:
    # Open file for reading
    li   $v0, 13       # system call for open file
    la   $a0, fin      # input file name
    li   $a1, 0        # flag for reading
    li   $a2, 0        # mode is ignored
    syscall            # open a file 
    move $s0, $v0      # save the file descriptor 

    # reading from file just opened
    li   $v0, 14       # system call for reading from file
    move $a0, $s0      # file descriptor 
    la   $a1, buffer   # address of buffer from which to read
    li   $a2, 100000   # hardcoded buffer length
    syscall            # read from file

jr $ra

output:
    li $v0, 4
    la $a0, msg2
    syscall

    li $v0, 1
    move $a0, $t1
    syscall

    li $v0, 4
    la $a0, nline
    syscall

    li $v0, 4
    la $a0, msg3
    syscall

    li $v0, 1
    move $a0, $t2
    syscall

    li $v0, 4
    la $a0, nline
    syscall

    li $v0, 4
    la $a0, msg4
    syscall

    li $v0, 1
    move $a0, $t3
    syscall

    li $v0, 4
    la $a0, nline
    syscall

    li $v0, 4
    la $a0, msg5
    syscall

    addi $t4, $t4, 1
    li $v0, 1
    move $a0, $t4
    syscall

jr $ra

checkUpper:
    blt $t5, 0x41, L1           #branch if less than 'A'
    bgt $t5, 0x5a, L1           #branch if greater than 'Z'
    addi $t1, $t1, 1            #increment Uppercase counter

    L1:
jr $ra

checkLower:
    blt $t5, 0x61, L2           #branch if less than 'a'
    bgt $t5, 0x7a, L2           #branch if greater than 'z'
    addi $t2, $t2, 1            #increment Lowercase counter

    L2:
jr $ra

checkDecimal:
    blt $t5, 0x30, L3           #branch if less than '0'
    bgt $t5, 0x39, L3           #branch if greater than '9'
    addi $t3, $t3, 1            #increment Decimal counter

    L3:
jr $ra

checkWord:
    bne $t5, 0x20, L4           #branch if 'space'
    addi $t4, $t4, 1            #increment words counter

    L4:
jr $ra

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

Note: I'm using MARS Simulator, if that makes any different

Update:
I have solved the problem by writing and calling the following procedure:

nameClean:
    li $t0, 0       #loop counter
    li $t1, 21      #loop end
clean:
    beq $t0, $t1, L5
    lb $t3, fin($t0)
    bne $t3, 0x0a, L6
    sb $zero, fin($t0)
    L6:
    addi $t0, $t0, 1
j clean
L5:
jr $ra

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

甜柠檬 2024-09-03 20:17:37

字符 10 (0xa) 是用于换行的 Ascii 代码,许多 *nix 操作系统将其用作行终止符。它不应该是文件名的一部分。只要把它脱掉就可以了。此外,此类操作系统使用 0 作为字符串终止符。它应该位于文件名的末尾,除非 open 调用采用字符数参数。

解决方案是获取用户的回复,找到字符 10 并将其替换为 0。使用结果作为要打开的文件名。

Character 10 (0xa) is the Ascii code for linefeed, which many *nix operating systems use for line terminator. It should not be part of the filename. Just strip it off. Also, such operating systems use 0 for a string terminator. It should be at the end of the filename unless the open call takes a number of characters parameter.

The solution is to take the user's reply, find character 10 and replace it with zero. Use the result as the filename to open.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文