(1 respuesta)
Traducir la función C con argumentos a MIPS: recorrer una matriz int y contar los negativos(2 respuestas)
Lenguaje ensamblador MIPS atravesando una matriz(1 respuesta)
¿Recorriendo la matriz usando el bucle while? - MIPS [duplicado](1 respuesta)
Cerradohace 2 años
.Quiero replicar esto de la manera más limpia posible
En Python
A = [0,0,0,0,0]
i = 0
while(i != 5):
A[i] = 10
i++
Es decir, quiero iterar a través de una matriz y establecer todos sus valores en [10,10,10,10,10]
Esto es lo que he hecho en el ensamblaje de mips
.data
array: .word 0:5
.text
main:
li $t1, 0 # i = 0
la $t9, array # $t9 = addr(array)
li $t8, 10 # $t8 = 10
start_loop:
beq $t1, 5, end_loop # if i == 5 jump to end loop
sll $t2, $t1, 2 # $t2 = i x 4
add $t2, $t9, $t2 # $t3 = addr(array[i])
sw $t8, 0($t2) # array[i] = $t8
addi $t1, $t1, 1 # i = i + 1
j start_loop
end_loop:
li $v0, 10 # end program
syscall
Siento que uséTantos registros y esta no es la forma más limpia de hacerlo. Cualquier ayuda se agradece
(También me aseguro de usar un bucle. Podría codificar esto sin un bucle, pero solo estoy tratando de encontrar otras formas de usar bucles)
La versión final totalmente optimizada en la respuesta de Craig sobre la traducción de la función C con argumentos a MIPS: recorrer una matriz int y contar los negativos es lo que debería estar haciendo. Dentro del bucle, solo hay 3 instrucciones para su caso: sw / addiu puntero incrementado en 4 / bne $p, $endp, top_of_loop (donde endp es un puntero a 1 después del final y(Ya calculaste antes, antes del ciclo). Como no lo necesitas dentro del bucle, optimízalo.
-Peter Cordes27/03/2021 a las 13:28
.data
array: .word 0:5
array_end:
.text
main:
la $t2, array
addiu $t1, $t2, 20 # one-past-end address for loop condition
# or la $t1, array_end to avoid hard-coding length
li $v0, 10
start_loop: # do{
sw $v0, 0($t2) # array[i] = $t8
addiu $t2,$t2,4 #increment pointer after
beq $t1, $t2, start_loop # }while(p != endp);
#end_loop:
#li $v0, 10 # exit call number happens to be the same value we wanted to store
syscall # exit
Alteraciones (con ayuda de Peter)
Así que lo primero que se hizo fue eliminar la variable i. En lugar de eso, podemos comparar la dirección de $t2, el puntero a la matriz, con el puntero final que configuramos fuera del bucle ($t1), eso nos dirá que hemos terminado. Ramificando al start_loop si no.
Los incrementos del puntero en lugar de rehacer la indexación cada vez son especialmente buenos en máquinas como MIPS que no tienen modos de direccionamiento indexados.
Bucleg con la rama condicional en la parte inferior del bucle significa que no necesita una instrucción j y es idiomático para el lenguaje ensamblador en todos (?) ISA (por ejemplo, ¿por qué los bucles siempre se compilan en el estilo "hacer...mientras" ( salto de cola)?). Es especialmente bueno cuando sabes que el bucle definitivamente se ejecutará al menos una vez, por lo que no necesitas una rama delante del bucle para tal vez omitirlo.
Respondido27 de marzo de 2021 a las 12:30
Cansado pero despiertoCansado pero despierto
157
1
1 insignia de plata
9
9 insignias de bronce
5
Eso es una mejora, pero no es necesario dentro del bucle, por lo que puedes guardar instrucciones en el bucle simplemente incrementando el puntero. (Con bne $t1, $t2, start_loop en la parte inferior como rama del bucle). Consulte los duplicados vinculados de esta pregunta para obtener mejores ejemplos. Tenga en cuenta que beq $t1, 5 necesita un registro temporal interno para cargar un 5, por lo que en realidad es bastante ineficiente. Si fuera a utilizar un registro de contador separado, agregaría $t1, $t1, -1 / bnez $t1, start_loop en la parte inferior.
-Peter Cordes27/03/2021 a las 13:51
Sí, esa es la idea correcta, pero aún necesitas iniciar t2 en el puntero inicial. Así que también puedes hacer $t2, array / addiu $t1, $t2, 20. (O pegar una etiqueta al final de la matriz y $t1, array_end, para no tener que esforzarte). codifica el tamaño en cualquier lugar, aunque el ensamblador integrado limitado de MARS no te permitirá hacer cosas como .equ arrlen, . - array para que calcule una longitud por ti).
-Peter Cordes28 de marzo de 2021 a las 0:24
Además, optimización divertida: podrías usar $v0 para retener 10, por lo que necesitarás retener un 10 más tarde para la llamada al sistema de salida.
-Peter Cordes28 de marzo de 2021 a las 0:26
@PeterCordes gracias por esto una vez más. Apreciado.
- Cansado pero despierto28 de marzo de 2021 a las 0:35
Edité tu conjunto por estilo, p. quitar cComentarios que no añaden nada y ordenan la sangría. También se agregó alguna explicación más. Por supuesto, siéntete libre de editar todo esto con tus propias palabras; es tu respuesta y esta es solo mi sugerencia.
-Peter Cordes28 de marzo de 2021 a las 0:43
.data
array: .word 0:5
.text
main:
li $t1, 0 #initialize i = 0
la $t2, array #load address of array[0]
li $t3, 10 #save 10 in a register
loop:
beq $t1, 5, end #if i == 5, end
sw $t3, ($t2) #array[i] = 10
add $t2, $t2, 4 #increment array address pointer by 4
add $t1, $t1, 1 #i = i + 1
j loop
end:
li $v0, 10
syscall
Compartir
Seguir
editado 27 de marzo de 2021 a las 12:38
Respondido27 de marzo de 2021 a las 12:31 p.m.
falsofalso
1
1
1 insignia de bronce