Почему использование регистра $ v0 в al oop возвращает неправильный вывод? - PullRequest
1 голос
/ 02 марта 2020

Следующая программа

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

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

Следующий код не возвращает ожидаемый результат

findMin:

      addi $t0, $a0, 0        # initialise $t0 (current pointer) to lower bound 
      addi $t1, $a0, 0        # initialise minimum pointer to upper bound 
      lw   $t2, 0($t1)        # initialise min (value) to the lower bound  


Loop: slt $t4, $a1, $t0
      bne $t4, $zero, End     # branch to end if upper < lower

      lw, $t3, 0($t0)         # store the content of the current pointer
      slt $t4, $t3, $t2       # if current ($t3) < min ($t2), store 1 in $t4
      beq $t4, $zero, LoopEnd # if it is 0, go to LoopEnd

      addi $t2, $t3, 0        # store content ($t3) as minimum ($t2)
      addi $v0, $t0, 0        # store the address of min (DIFFERENCE)

LoopEnd: addi $t0, $t0, 4     # increments current pointer lower bound 
         j Loop               # Jump to loop 

End:     jr $ra               # return from this function

Однако следующий код не возвращает ожидаемое значение:

findMin:
    addi $t0, $a0, 0  # $t0 is the pointer to the current item
    addi $t1, $a0, 0  # $t1 is the pointer to the minimum item
    lw   $t2, 0($t1)  # $t2 stores the value of minimum item

loop:
    slt $t4, $a1, $t0  # check if last pointer < current pointer
    bne $t4, $zero, exit # if current pointer > last pointer, exit
    lw  $t3, 0($t0)    # $t3 stores the value of current item
    slt $t4, $t3, $t2  # if the current value is lesser than minimum value
    beq $t4, $zero, skip # if current value is not lesser, then skip

    addi $t1, $t0, 0   # minimum pointer = current pointer (DIFFERENCE)
    lw   $t2, 0($t1)   # $t2 stores the value of minimum item

skip:
    addi $t0, $t0, 4   # move to the next item
    j loop
exit:   
    addi $v0, $t1, 0   # $v0 stores the address of the minimum item (DIFFERENCE)
    jr $ra          # return from this function

Что стоит за этим ?

Ниже приводится полный код (необязательно)


# arrayFunction.asm
       .data 
array: .word 8, 2, 1, 6, 9, 7, 3, 5, 0, 4
newl:  .asciiz "\n"

       .text
main:
    # Print the original content of array
    # setup the parameter(s)
    # call the printArray function
    la $a0, array            # base address of array
    la $a1, 10               # number of elements in array
    jal printArray           # call function 


    # Ask the user for two indices
    li   $v0, 5             # System call code for read_int
    syscall 
    add  $t0, $v0, $zero    # store input in $t0          

    li   $v0, 5             # System call code for read_int
    syscall           
    add  $t1, $v0, $zero    # store input in $t1          

    # Call the findMin function
    # setup the parameter(s) 
    la $a0, array       # load address of array into $a0
    la $a1, array       # load address of array into $a1
    sll $t0, $t0, 2         # calculate offset of lower bound
    sll $t1, $t1, 2         # calculate offset of upper bound
    add $a0, $a0, $t0       # set $a0 to the lower bound
    add $a1, $a1, $t1       # set $a1 to the upper bound 

    # call the function
    jal findMin             # call function 


    # Print the min item
    # place the min item in $t3 for printing
    addi $t3, $t2, 0        # placing min item in $t3 
    addi $t4, $v0, 0        # saving the pointer to the min element

    # Print an integer followed by a newline
    li   $v0, 1             # system call code for print_int
    addi $a0, $t3, 0        # print $t3
    syscall                 # make system call

    li   $v0, 4             # system call code for print_string
    la   $a0, newl      
    syscall                 # print newline

    #Calculate and print the index of min item
    la  $a0, array
    sub $t3, $t4, $a0   
    srl $t3, $t3, 2 

    # Place the min index in $t3 for printing   

    # Print the min index
    # Print an integer followed by a newline
    li   $v0, 1         # system call code for print_int
    addi $a0, $t3, 0    # print $t3
    syscall             # make system call

    li   $v0, 4         # system call code for print_string
    la   $a0, newl      
    syscall             # print newline

    # End of main, make a syscall to "exit"
    li   $v0, 10        # system call code for exit
    syscall             # terminate program


#######################################################################
###   Function printArray   ### 
#Input: Array Address in $a0, Number of elements in $a1
#Output: None
#Purpose: Print array elements
#Registers used: $t0, $t1, $t2, $t3
#Assumption: Array element is word size (4-byte)
printArray:
    addi $t1, $a0, 0    #$t1 is the pointer to the item
    sll  $t2, $a1, 2    #$t2 is the offset beyond the last item
    add  $t2, $a0, $t2  #$t2 is pointing beyond the last item
l1: 
    beq  $t1, $t2, e1
    lw   $t3, 0($t1)    # $t3 is the current item
    li   $v0, 1         # system call code for print_int
    addi $a0, $t3, 0    # integer to print
    syscall             # print it
    addi $t1, $t1, 4
    j l1            # Another iteration
e1:
    li   $v0, 4         # system call code for print_string
    la   $a0, newl      # 
    syscall             # print newline
    jr $ra          # return from this function


#######################################################################
###   Student Function findMin   ### 
#Input: Lower Array Pointer in $a0, Higher Array Pointer in $a1
#Output: $v0 contains the address of min item 
#Purpose: Find and return the minimum item 
#              between $a0 and $a1 (inclusive)
#Registers used: $t0 (counter), $t1 (max add), $t2 (min), $v0 (min pos), $t3 (current item)
#Assumption: Array element is word size (4-byte), $a0 <= $a1
findMin:

      addi $t0, $a0, 0        # initialise $t0 (current pointer) to lower bound 
      addi $t1, $a0, 0        # initialise minimum pointer to upper bound 
      lw   $t2, 0($t1)        # initialise min (value) to the lower bound  


Loop: slt $t4, $a1, $t0
      bne $t4, $zero, End     # branch to end if upper < lower

      lw, $t3, 0($t0)         # store the content of the current pointer
      slt $t4, $t3, $t2       # if current ($t3) < min ($t2), store 1 in $t4
      beq $t4, $zero, LoopEnd # if it is 0, go to LoopEnd

      addi $t2, $t3, 0        # store content ($t3) as minimum ($t2)
      addi $t1, $t0, 0        # store the address of min

LoopEnd: addi $t0, $t0, 4     # increments current pointer lower bound 
         j Loop               # Jump to loop 

End:    addi $v0, $t1, 0       
    jr $ra                # return from this function

1 Ответ

1 голос
/ 02 марта 2020

В первом случае проблема заключается в том, что вы изначально сохраняете указатель min в регистр t1, но по возвращении ожидаете, что он будет на v0. Теперь в случаях, когда минимальное значение не совсем соответствует нижнему индексу, это не будет проблемой, поскольку в l oop вы сохраняете новый указатель найденных минимальных значений в v0, поэтому при возврате uppon все будет как ожидается. Но в случае, как 2,4, минимальное значение в нижней границе здесь так же, как в индексе 2, поэтому в l oop, так как новые минимальные точки не найдены, таким образом, ничего не будет записано в v0, поэтому при возврате оно будет иметь некоторые значения мусора.

Измените начальную часть на эту, и она будет работать нормально:

      addi $v0, $a0, 0        # initialise minimum pointer to upper bound 
      lw   $t2, 0($v0)        # initialise min (value) to the lower bound 
...