РЕДАКТИРОВАТЬ: ответ на исходный вопрос состоял в том, что исходный код заполнял выходной буфер только байтами, соответствующими содержанию слов, но оставлял неопределенную память между ними, что обнуляется в симуляторе MARS, поэтому случайно был нулевой терминаторпосле первого слова, и служба «print string» в MARS действительно ожидает строки с нулевым символом в конце = было напечатано только первое слово.
Вот мой вариант для той же задачи, используя различные сочетания клавиш для выполнениято же самое в (незначительно) меньшем количестве инструкций (это все еще сложность O (N)).
Также я написал это таким образом, чтобы обеспечить правильную работу ввода с несколькими пробелами, начиная / заканчивая пробелом или пустым вводом (для «двух пробелов» при вводе он также выведет «два пробела») (я не проверял все это с вашим исходным кодом, поэтому я не говорю, что есть какая-то ошибка, кажется, она должна хорошо обрабатывать большинство из них,Я только что тщательно проверил только мой вариант):
# delayed branching should be OFF
.data
prompt: .asciiz "Enter a string: "
msgout: .asciiz "Output string: "
input: .space 256
output: .space 256
.text
.globl main
main:
li $v0, 4 # Print enter a string prompt
la $a0, prompt
syscall
li $v0, 8 # Ask the user for the string they want to reverse
la $a0, input # We'll store it in 'input'
li $a1, 256 # Only 256 chars/bytes allowed
syscall
la $a1, output
# a0 = input, a1 = output
new_word:
move $t0, $zero # t0 word length = 0
li $t1, '0' # t1 uppercase counter = '0' (ASCII counter)
word_parse_loop:
lbu $t2, ($a0) # next input character
addi $a0, $a0, 1 # advance input pointer
bltu $t2, 33, word_done # end of word detected (space or newline)
# "less than 33" to get shorter code than for "less/equal than 32"
addi $t0, $t0, 1 # ++word length
# check if word character is uppercase letter
addiu $t2, $t2, -65 # subtract 'A' => makes t2 = 0..25 for 'A'..'Z'
sltiu $t3, $t2, 26 # t3 = (t2 < 26) ? 1 : 0
add $t1, $t1, $t3 # ++uppercase counter if uppercase detected
j word_parse_loop
word_output_fill:
# loop to fill output with uppercase-counter (entry is "word_done" below)
sb $t1, ($a1)
addi $a1, $a1, 1
addiu $t0, $t0, -1
word_done:
# t0 = word length, t1 = uppercase ASCII counter, t2 = space, newline or less
# a0 = next word (or beyond data), a1 = output pointer (to be written to)
bnez $t0, word_output_fill
bltu $t2, ' ', it_was_last_word
# t2 == space, move onto next word in input (store space also in output)
sb $t2, ($a1)
addi $a1, $a1, 1
j new_word
it_was_last_word:
# finish output data by storing zero terminator
sb $zero, ($a1)
# output result
li $v0, 4 # Print msgout
la $a0, msgout
syscall
li $v0, 4 # Print the output string!
la $a0, output
syscall
li $v0, 10 # exit()
syscall
Что нужно отметить («хитрости»?):
- uppeСчетчик rcase начинается со значения 48 (символ для нуля), поэтому «счетчик» все время содержит цифру ASCII (для счета меньше 10, для 10+ он переходит к другим символам, кроме цифр) и готов кзаписывается в строку без какого-либо преобразования (так как счетчик нигде не используется как «целое число», вы можете оптимизировать преобразование следующим образом).
- он последовательно проходит через ввод и вывод, никогда не читая некоторые данные дваждыили перенастройка позиции ввода / вывода, поэтому алгоритм, подобный этому, может работать также с данными, подобными «потоку» (он почти производит вывод 1: 1 для каждого входного символа, за исключением того, что вывод слегка задерживается «на слово», то есть он будет обрабатыватьвходной поток до «конца слова», затем создается целое выходное слово (эта архитектура может быть важна для некоторых входов / выходов, таких как магнитные ленты на входе и последовательный принтер на выходе).
- проверка на A.Диапазон букв в верхнем регистре .Z использует только одно условие сравнения (буква 'A' вычитается из символасначала введите cter, нормализуя значение в 0..25 для заглавных букв, а все остальное, когда рассматривается как целое число без знака, должно иметь значение больше 25, поэтому для обнаружения всех заглавных букв достаточно одного
< 26
теста. - счетчик в верхнем регистре обновляется каждый раз, добавляя либо 0, либо 1 (в зависимости от ранее упомянутого условия), что позволяет избежать дополнительных ветвлений в коде.Как правило, современные процессоры предпочитают больше кода без ветвления, поскольку они могут более агрессивно кэшировать / спекулировать впереди, поэтому в случаях, когда вероятность ветвления больше, чем 50%, вариант кода без ветвления обычно имеет лучшую производительность (для случаев, когда ветвлениенапример, 5-10% шансов, что ответвление от этого необычного условия и оставаться в очереди для общего случая может быть лучше, например, такие вещи, как «конец слова»).
Или, если у вас есть какие-либоДругой вопрос, касающийся конкретной части кода, не стесняйтесь задавать.