Почему это сработало? Печать массива в обратном порядке в MIPS

#arrays #integer #mips #reverse

#массивы #целое число #mips #обратный

Вопрос:

У меня есть проект для класса, и все шло нормально. Нам просто нужно было сохранить 20 целых чисел из пользовательского ввода в массив и распечатать их различными способами. Мой код работал, печатая его в правильном порядке, но когда я сделал это в обратном порядке, результат был довольно странным. Итак, не понимая, я вроде как понял суть проблемы с индексом, и по какой-то причине я решил ее? Но я не понимаю, действительно ли это правильно.

     # for reverse order that worked
    addi $t0, $zero, 76
    while:

        beq $t0, -4, exit

        lw $t1, inputArray($t0)

        li $v0, 1
        move $a0, $t1
        syscall

        li $v0, 4 
        la $a0, space
        syscall

        addi $t0, $t0, -4

        j while
  

Теперь вот что я сделал в первый раз:

      # reverse order that didn't work
     addi $t0, $zero, 76
     while:

        beq $t0, 0, exit

        lw $t1, inputArray($t0)

        li $v0, 1
        move $a0, $t1
        syscall

        li $v0, 4 
        la $a0, space
        syscall

        addi $t0, $t0, -4

        j while
  

Вывод, когда это не сработало, был:

1702129221 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2

Ответ №1:

Проблема существует даже с вашим рабочим кодом.

Действительно, использование inputArray($t1) — неподходящий способ доступа к вашему массиву. Ваш код будет нарушен, если адрес inputArray не может быть закодирован в 16 бит. И это затрудняет чтение вашего кода и повышает вероятность ошибок.

Что вам следует сделать, так это разделить счетчик циклов и вычисление индекса массива. Это примерно соответствует следующему псевдокоду C

 for(int i=20, array=amp;inputArray[20]; i!=0; i--, array--){
  print(*array," ");
  

Версия Asm

     # init part :: int i=20, array=inputArray[20];
    addi $t0, $zero, 20   # $t0 is loop counter i
    li $t2, inputArray # load 32 bits address of inputArray $t2=@inputArray
    addi  $t2, 76         # $t2=array=@inputArray[20]
while:
    beq $t0, zero, exit   # loop condition :: i!=0;
    # loop body :: print  *Array, " "
    lw $t1, 0($t2)
    addi $v0,zero, 1
    move $a0, $t1
    syscall
    # print space
    addi $v0,zero, 4 
    li $a0, space
    syscall
    # loop increments :: i--, array--
    addi $t0, $t0, -1  #i--
    addi $t2, $t2, -4  #array--
    j while
  

Разделение цикла и доступа к массиву всегда приводит к улучшению кода. И это намного проще, если вам нужно получать разные элементы массива за итерацию, например, для печати array[i]*array[i-1] или разных типов массивов intArray[i] =shortArray[i] .

Вашей проблемой с нерабочим кодом была неправильная проверка диапазона. С таким кодом он не может быть получен, если вы начинаете с рабочего кода на C.

Комментарии:

1. Спасибо, я допустил простую ошибку. Также спасибо за отличный совет по разделению цикла и доступа к массиву. Обязательно имейте это в виду.