reading the file name from user input in MIPS assembly

11,845

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.

Share:
11,845
Hassan Al-Jeshi
Author by

Hassan Al-Jeshi

Software Engineer - Web Developer

Updated on June 13, 2022

Comments

  • Hassan Al-Jeshi
    Hassan Al-Jeshi almost 2 years

    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