Объясняя раздел сборки кода MIPS? - PullRequest
0 голосов
/ 19 сентября 2019

Мы недавно написали этот код в классе.Я прошел и добавил комментарии, которые объясняют мне, как это работает.Я просто не понимаю, как цикл подсчитывает количество символов / пробелов в строке.Может ли кто-нибудь перевести это мне?

#Comment

.data

Str:.asciiz "hello worlds"

prompt:.asciiz "The given string is: "

ans:.asciiz "\n The number of chr and spaces is = "

.text



.globl main

main:

la $a0, prompt #load string prompt into register a0

li $v0, 4 #print string commmand(prints the prompt)

syscall #executes the command


la $a0, Str #loads Str into a0 

li $v0, 4 #print string commnad

syscall #executes the command


li $t0, 0 #set t0 to 0

la $t1, Str #load Str into register t1


Loop1: #begins the loop SECTION I DONT UNDERSTAND

lb $t2, 0($t1) #loads byte into t2?

beqz $t2, Tim #if t2 == to zero go to Tim ?

addi$t0,$t0,1 #incremet t0 by 1 ?

addi$t1,$t1,1 #initialize t1 to 1 ?

j Loop1

syscall #executes the loop


Tim:
la$a0,ans #load ans into a0

li$v0,4 #print ans string

syscall #executes command


move$a0,$t0 #move t0 to a0

li$v0,1 #print int

syscall #execute command

Ответы [ 2 ]

1 голос
/ 19 сентября 2019

Давайте с самого начала (пропустив 2 системных вызова перед циклом):

Анализируемая строка hello worlds расположена по адресу Str

t0 будет содержать числосимволов в hello worlds.Это то, что нам нужно найти и напечатать.Инициализируется нулем:
li $t0, 0

t1 содержит адрес обрабатываемого в данный момент символа.Он инициализируется Str, который является адресом hello worlds, и в то же время является адресом его первого символа h:
la $t1, Str

Цикл начинается:

iteration1:

Текущий обработанный символ загружен в t2:
lb $t2, 0($t1)
Напомним, что lb reg, offset(addr) подразумевает загрузку 1-байтового значения по адресу addr + offset в регистр reg.В нашем случае это подразумевает загрузку 1-байтового значения по адресу t1 + 0 в t2.t1 + 0 - адрес текущего символа, т.е. h.Следовательно, h загружается в t2

beqz $t2, Tim подразумевает переход к метке Tim в случае, если t2 равен нулю.но t2 имеет значение h, поэтому оно не равно нулю.Цель этой проверки - обнаружить нулевой терминатор, который обозначает конец строки.Как только мы обнаружим этот нулевой терминатор, мы все закончили, и цикл должен завершиться

addi $t0, $t0, 1 - мы увеличиваем наш счетчик (количество символов, которые мы обработали до сих пор).t0 становится 1

addi $t1, $t1, 1 - мы увеличиваем адрес обрабатываемого в данный момент символа.Другими словами, мы переходим к следующему символу строки (мы увеличиваем его на 1, потому что размер символа составляет 1 байт).Теперь t1 имеет адрес второго символа, который e

j Loop1 - мы начинаем новую итерацию

итерацию 2:

lb $t2, 0($t1) -e загружено в t2
beqz $t2, Tim - e не равно нулю, поэтому мы не переходим к Tim и продолжаем цикл
addi $t0, $t0, 1 - t0 становится 2
addi $t1, $t1, 1 - t1 содержит адрес третьего символа, который l
j Loop1 - начать новую итерацию

и так далее, пока beqz $t2, Tim не проверит, что t2 содержит ноль,в этом случае программа останавливает цикл и переходит к Tim

0 голосов
/ 19 сентября 2019

Этот код считает байты в строке C в стиле C с нулевым символом в конце.

Давайте переведем это в C, чтобы посмотреть, что он делает, здесь мы используем поток сборки, имитирующий стиль if-goto:control.

Loop1:
  int ch = *ptr;
  if ( ch == 0 ) goto Tim;      // ch is $t2
  counter++;                    // counter is $t0
  ptr++;                        // ptr is $t1
  goto Loop1;

И если мы переведем это на структурированное программирование, мы получим:

while ( *ptr != '\0' ) { ptr++; counter++; }

Имеет смысл?


В сторону, syscall только после того, как цикл не имеет какой-либо нормальной настройки системного вызова, это выглядит подозрительно;однако, чтобы было ясно, это мертвый код - код, расположенный между безусловным переходом и следующей меткой, (почти) определенно недоступен для любого потока управления программой (мы называем этот мертвый код; он должен быть удален - икомментарий ошибочен).


Использование $t0 - регистр энергозависимости (нуля) соглашения о вызовах - для удержания счетчика в реальном времени через системный вызов в стиле печати также подозрительно.Иногда это будет работать, но в других средах нет.Было бы более целесообразно использовать регистр сохраняемых / энергонезависимых вызовов, например $s0, или расположение в памяти, а не полагаться на то, что $ t0 не изменится.

...