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
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.