MIPS: разбор и изменение строки - PullRequest
0 голосов
/ 23 марта 2019

Мне нужно написать программу на MIPS, в которой я должен открыть файл, имя которого введено пользователем, и проанализировать его с помощью симулятора MARS. Однако, поскольку системный вызов 8 (который читает строку из пользовательского ввода) следует семантике функции fgets C, мне нужно удалить символ перевода строки \ n из строки, прежде чем я смогу попытаться открыть файл.

Я могу разобрать строку (здесь я печатаю код ASCII каждого символа для целей отладки). Однако, когда я пытаюсь изменить символ перевода строки на символ NULL со строкой

sb $zero 0($t1)

Марс встречает исключение во время выполнения:

"Исключение во время выполнения по адресу 0x00400050: адрес вне диапазона 0x00000000"

Если я закомментирую эту строку, программа работает нормально и печатает каждый код строки ascii.

.data

prompt : .asciiz "enter filename:\n"
lf : .asciiz "\n"
space : .asciiz " "

.text 

la $a0 prompt      # asking user for filename
jal print_string
jal read_string

la $t0 ($a0)   #copying the string address 
lb $t1 0($t0)  #loading the first  byte

parsing_string : #loop
beq $t1 0 remove_line_feed  # reaching the NULL character '\0'

move $a0  $t1   #printing the ascii code
li $v0 1 
syscall

la $a0 space  #printing a space
li $v0 4
syscall  

add $t0 $t0 1   # loading  
lbu $t1 ($t0)   # the next byte

j parsing_string

remove_line_feed :
sb $zero 0($t1)   # runtime exception if i uncomment  this line 
j end

end : 


li $v0 10     # syscall 10 : end program 
syscall



read_string :   #read a string in $a0

li $a1 100  # $a1 = maximum number of characters to read        
li $v0 8    # syscall 8  : fgets()
syscall 
jr $ra


print_string  :  #print string in $a0
li $v0 4      # syscall 4 : print string
syscall
jr $ra

Я не понимаю, что я делаю здесь неправильно, в этой точке программы регистр $ t1 должен содержать адрес, на котором написан символ перевода строки. Однако я, возможно, неправильно понял, как инструкции сохраняют байт и загружают байт на самом деле.

Любая помощь или предложения с благодарностью:)

1 Ответ

0 голосов
/ 24 марта 2019

в асм код

sb $zero 0($t1)   # runtime exception if i uncomment  this line 

вы используете $t1 в качестве адреса байта, который хотите очистить.

Но это не так. Вы использовали

la $t0 ($a0)   #copying the string address 

и все ваши доступы используют $t0.

В конце вашей функции parsing_string вы читаете символ по адресу $t0 и вставляете его в $t1:

lbu $t1 ($t0)   # the next byte

, затем вы вернетесь к parsing_string, проверьте, если t1 равно 0

beq $t1 0 remove_line_feed  # reaching the NULL character '\0'

перейти к remove_line_feed

remove_line_feed :
sb $zero 0($t1)   # runtime exception if i uncomment  this line 
j end

Где вы пытаетесь написать ноль по адресу 0+$t1 (который вы только что проверили как равный нулю).

И симулятор правильно сообщает вам, что вы пытаетесь написать по адресу 0, и выдает ошибку.

Если вы измените свой код на

remove_line_feed :
sb $zero 0($t0)   # runtime exception if i uncomment  this line 
j end

это удалит ошибку времени выполнения.

Но это не сделает ваш код правильным. То, что вы хотите сделать, это очистить '\ n', который является непосредственно перед \0, и ваш код должен быть

remove_line_feed :
sb $zero -1($t0)    
j end

Кроме того, вы можете изменить сравнение и вместо поиска окончательного \0 строки выполнить поиск по 10 (перевод строки ascii) и заменить тот же символ на 0.

...