• Viernes 29 de Marzo de 2024, 10:35

Autor Tema:  RLE en ensamblador MIPS  (Leído 23364 veces)

manurodri189

  • Miembro MUY activo
  • ***
  • Mensajes: 117
    • Ver Perfil
Re: RLE en ensamblador MIPS
« Respuesta #50 en: Viernes 5 de Junio de 2009, 14:01 »
0
Cierto, tengo que coger soltura con esto, vamos a ver:

Lo de avanzar el puntero, error tonto,

Código: ASM
  1.  #avanzo el puntero
  2.  
  3.     addiu $t3,$t3,1
  4.     addiu $t4,$t4,1
  5.  

Y lo del syscall error tonto tambien, solamente tengo que cambiar el 4 por un 1.

Y ahora creo que lo otro te he entendido, pongo lo que he modificado:

Código: ASM
  1. start:
  2.     la $s0, Entrance
  3.     la $s3, encode1  #almaceno la direccion de encode1 en s3, s3 es el puntero
  4.     la $s4, encode2  #almaceno la direccion de encode2 en s4, s4 es el puntero
  5.     or $a3,$zero,s3
  6.     or $a4,$zero,s4
  7.  

Como aqui solo entra una vez, pues preparo los registros, no es asi?

Código: ASM
  1. almacenar:
  2.  
  3.     sb $a0,0($a3)   #meto el caracter en la primera direccion de s3
  4.     sw $a1,0($a4)   #meto el contador en la primera direccion de s4
  5.  
  6.     #avanzo el puntero
  7.  
  8.     addiu $a3,$a3,1
  9.     addiu $a4,$a4,1
  10.  
  11. # Volvemos de la función
  12.     jr $ra
  13.     nop
  14.  

Lo unico que me da errores en los or, no se hacia asi? independientemente de los errores en los or, la idea es esa, verdad?

Salu2



m0skit0

  • Miembro de PLATA
  • *****
  • Mensajes: 2337
  • Nacionalidad: ma
    • Ver Perfil
    • http://fr33kk0mpu73r.blogspot.com/
Re: RLE en ensamblador MIPS
« Respuesta #51 en: Viernes 5 de Junio de 2009, 14:21 »
0
Primero, te has olvidado de sw guarda 4 bytes y no 1, por tanto hay que avanzar el puntero 4 bytes y no 1  :P

Código: Text
  1.  #avanzo el puntero
  2.  
  3.     addiu $a3,$a3,1
  4.     addiu $a4,$a4,4
  5.  

Cita de: "manurodri189"
solamente tengo que cambiar el 4 por un 1
Eso te imprime 1 número, no un vector de números. Tendrías que hacer un bucle de impresión. La cuestión es cuándo parar  :lol:

Cita de: "manurodri189"
independientemente de los errores en los or, la idea es esa, verdad?
El error de los or es porque te has olvidado el $. Y la idea es algo así, aunque personalmente no lo haría de esa manera. Pero creo que así funcionaría. Ya me cuentas.

PD: ¿qué paso con $a2? xD

manurodri189

  • Miembro MUY activo
  • ***
  • Mensajes: 117
    • Ver Perfil
Re: RLE en ensamblador MIPS
« Respuesta #52 en: Viernes 5 de Junio de 2009, 14:46 »
0
Pues el 2 lo he acabado usando porque con el 4 no me dejaba.

Pues lo que esta hecho funciona, al menos con los caracteres, ya que estos si me los imprime correctamete.

Lo de la impresion de los numeros de momento, como era de prueba no lo voy a hacer. Asi que supongo que en encode1, tengo los caracteres, y en encode2, las veces que se repite.

Ahora he creado un nuevo "vector" encode, tendria que almacenar un numero, una letra, y asi, hasta que no sea final de caracter, no es asi? algo como el siguiente caracter, no?

Por cierto recuerdo que el enter me lo contaba, como lo puedo eliminar de encode 1 y de encode2?

Salu2



m0skit0

  • Miembro de PLATA
  • *****
  • Mensajes: 2337
  • Nacionalidad: ma
    • Ver Perfil
    • http://fr33kk0mpu73r.blogspot.com/
Re: RLE en ensamblador MIPS
« Respuesta #53 en: Viernes 5 de Junio de 2009, 17:35 »
0
Cita de: "manurodri189"
Pues el 2 lo he acabado usando porque con el 4 no me dejaba.
Normal, no existe el registro $a4  :P

Cita de: "manurodri189"
Asi que supongo que en encode1, tengo los caracteres, y en encode2, las veces que se repite.
¿Supones? No necesitas suponer nada, tienes el contenido de la memoria a la vista, hombre...

Cita de: "manurodri189"
Ahora he creado un nuevo "vector" encode, tendria que almacenar un numero, una letra, y asi, hasta que no sea final de caracter, no es asi?
Sí, pero tu problema ahora va a ser el alineamiento. Es decir, si guardas un byte y una palabra, la palabra no va a estar alineada en una dirección múltiplo de 4 bytes y te va a dar error de alineamiento. Esto lo puedes solucionar de 2 formas: o bien convirtiendo los bytes en palabras (con el consiguiente gasto de memoria) o bien conviertes los números en bytes (con la consiguiente pérdida de rango).

Cita de: "manurodri189"
Por cierto recuerdo que el enter me lo contaba, como lo puedo eliminar de encode 1 y de encode2?
Mejor elimínalo al principio, justo tras guardar la cadena en Encode. Ya que es el penúltimo carácter, debería ser algo sencillo.

manurodri189

  • Miembro MUY activo
  • ***
  • Mensajes: 117
    • Ver Perfil
Re: RLE en ensamblador MIPS
« Respuesta #54 en: Sábado 6 de Junio de 2009, 12:43 »
0
Cita de: "m0skit0"
Sí, pero tu problema ahora va a ser el alineamiento. Es decir, si guardas un byte y una palabra, la palabra no va a estar alineada en una dirección múltiplo de 4 bytes y te va a dar error de alineamiento. Esto lo puedes solucionar de 2 formas: o bien convirtiendo los bytes en palabras (con el consiguiente gasto de memoria) o bien conviertes los números en bytes (con la consiguiente pérdida de rango).

Que quieres decir con perdida de rango? si lo pmeto como byte, no podre operar con el como numero? porque lo necesitaria para decodificarlo, no? y si lo meto como palabra, a la hora de imprimirlo chungo, no? que me recomiendas?

Citar
Mejor elimínalo al principio, justo tras guardar la cadena en Encode. Ya que es el penúltimo carácter, debería ser algo sencillo.

Osea antes de meterlo a encode, directamente no lo meto y listo, no? esa es la idea verdad? Y para la decodificacion posterior algo parecido, no?

Salu2



m0skit0

  • Miembro de PLATA
  • *****
  • Mensajes: 2337
  • Nacionalidad: ma
    • Ver Perfil
    • http://fr33kk0mpu73r.blogspot.com/
Re: RLE en ensamblador MIPS
« Respuesta #55 en: Sábado 6 de Junio de 2009, 13:10 »
0
Cita de: "manurodri189"
Que quieres decir con perdida de rango?
¿Qué diferencia hay entre un número de un byte y uno de una palabra?

Cita de: "manurodri189"
Osea antes de meterlo a encode, directamente no lo meto y listo, no?
No puedes evitar que se meta, puesto que tú no controlas lo que hace la llamada al sistema. Lo único que te queda es quitarlo después de que la llamada al sistema lo hay metido en el buffer.

manurodri189

  • Miembro MUY activo
  • ***
  • Mensajes: 117
    • Ver Perfil
Re: RLE en ensamblador MIPS
« Respuesta #56 en: Sábado 6 de Junio de 2009, 13:16 »
0
Cita de: "m0skit0"
¿Qué diferencia hay entre un número de un byte y uno de una palabra?.

Pues no lo se tío, el tamaño seguro, porque una palabra son 4 bytes, pero no se la diferencia a la hora de operar.

Salu2



m0skit0

  • Miembro de PLATA
  • *****
  • Mensajes: 2337
  • Nacionalidad: ma
    • Ver Perfil
    • http://fr33kk0mpu73r.blogspot.com/
Re: RLE en ensamblador MIPS
« Respuesta #57 en: Sábado 6 de Junio de 2009, 14:41 »
0
El tamaño, evidentemente, por tanto en 4 bytes podemos tener números más grandes que en un byte, ¿no? A la hora de operar no tienes ninguna diferencia.

manurodri189

  • Miembro MUY activo
  • ***
  • Mensajes: 117
    • Ver Perfil
Re: RLE en ensamblador MIPS
« Respuesta #58 en: Viernes 12 de Junio de 2009, 09:28 »
0
Despues de unos dias ocupado con otras cosas, he vuelto a la carga con esto, a ver si ya lo acabo que creo que queda poquito.

Al final me decidí por la perdida de rango, entoces solamente tendria que hacer la siguiente modificacion:

Código: ASM
  1. almacenar:
  2.  
  3.     sb $a0,0($a3)   #meto el caracter en la primera direccion de a3
  4.     sb $a1,0($a2)   #meto el contador en la primera direccion de a4
  5.  
  6.     #avanzo el puntero
  7.  
  8.     addiu $a3,$a3,1
  9.     addiu $a2,$a2,1
  10.  

Osea almacenar un byte en vez de una palabra, y el desplazamiento 1 en vez de 4, cierto?

Otra cosa, me dices que para eliminar el caracter "enter" seria una vez lo tengo en el buffer quitarlo, y que es relativamente facil, mira tengo esto:

Código: ASM
  1. #Almacenar el String en la matriz
  2. # Número de syscall
  3.     ori $v0,$zero,8
  4. # $a0 = buffer para guardar la cadena
  5.     la $a0,Entrance
  6. # $a1 = tamaño a leer
  7.     ori $a1,$zero,80
  8.     syscall
  9.  

Ahora mismo tengo la cadena en Entrance, incluyendo el caracter "enter", no se me ocurre como, o almenos una manera sencilla, se me ocurre, que una vez tenga la cadena medita en Entrance, calcular el tamaño de entrance, y volver a leer pero ahora desde Entrance, a una nueva matriz, donde el tamaño sea el tamaño de Entrance-1, pero esto no se me ocurre como hacerlo y menos de manera sencilla, alguna solución mas factible?

Salu2

PD: Muchas gracias de nuevo.



manurodri189

  • Miembro MUY activo
  • ***
  • Mensajes: 117
    • Ver Perfil
Re: RLE en ensamblador MIPS
« Respuesta #59 en: Viernes 12 de Junio de 2009, 09:41 »
0
Por cierto para almacenar en encode la salida final, he hecho algo así:

Código: ASM
  1. almacenar_salida:
  2.     sb encode1,0($a0)
  3.     sb encode2,0($a1)
  4.     sb encode,0($a3)
  5.  
  6. while:
  7.  
  8.     beq $a0, $zero, finwhile    #si es el caracter vacio acabo
  9.     lbu $a3,0($a1)              #cargo el primer numero en encode
  10.     addiu $a3,$a3,1             #avanzo el puntero de encode
  11.     lbu $a3,0($a0)              #cargo el caracter en encode
  12.  
  13.     #avanzo todos los punteros
  14.     addiu $a3,$a3,1
  15.     addiu $a2,$a2,1
  16.     addiu $a1,$a1,1
  17.  
  18.     jal while                   #llamo a while de nuevo
  19.  
  20.  
  21. finwhile:
  22.  
  23. # Volvemos de la función
  24.     jr $ra
  25.     nop
  26.  

Que te parece?

Salu2

Edito: para almacenar la direccion hay que usar esto que se me habia pasado:

Código: ASM
  1. almacenar_salida:
  2.     la $a0,encode1
  3.     la $a1,encode2
  4.     la $a3,encode
  5.  



manurodri189

  • Miembro MUY activo
  • ***
  • Mensajes: 117
    • Ver Perfil
Re: RLE en ensamblador MIPS
« Respuesta #60 en: Viernes 12 de Junio de 2009, 11:09 »
0
Bueno he seguido trabajando, y creo que ya he acabado el programa, pero obviamente no funciona, te pego el código.

Código: ASM
  1. .data
  2. Entrance: .space 80
  3. Entranceaux: .space 80
  4. encode1: .space 40
  5. encode2: .space 40
  6. encode: .space 40
  7. decode: .space 80
  8. msg1: .asciiz "Please insert the String: "
  9. msg2: .asciiz " "
  10. msg3: .asciiz "n String encode like: "
  11. msg4: .asciiz "n String decode like: "
  12. .text
  13. .globl main
  14.  
  15. #
  16. # Main
  17. #
  18. main:
  19.     ori $v0,$zero,4
  20.     la $a0,msg1
  21.     syscall
  22.  
  23. #Almacenar el String en la matriz
  24. # Número de syscall
  25.     ori $v0,$zero,8
  26. # $a0 = buffer para guardar la cadena
  27.     la $a0,Entranceaux
  28. # $a1 = tamaño a leer
  29.     ori $a1,$zero,80
  30.     syscall
  31.  
  32. #quitar el ultimo caracter de entrance.
  33.  
  34. la $a0,Entrance         #Almaceno la entrada sin el caracter "enter"
  35. la $a1,Entranceaux      #Cadena de entrada
  36. la $a2,Entranceaux+1´   #puntero al segundo caracter de la cadena de entrada
  37.  
  38. recorrer:
  39.     beq $a2, $zero, imprimir
  40.     lbu $a0,0($a1)      #meto el caracter
  41.  
  42.     #avanzo todos los punteros
  43.     addiu $a2,$a2,1
  44.     addiu $a0,$a0,1
  45.     addiu $a1,$a1,1
  46.      
  47.     j recorrer
  48.  
  49.  
  50. imprimir:
  51.  
  52. #Imprimir la matriz
  53. # Número de syscall
  54.     ori $v0,$zero,4
  55. # $a0 = buffer a imprimir
  56.     la $a0,Entrance
  57.     syscall
  58.  
  59. #
  60. # Codificar
  61. #
  62. start:
  63.     la $s0, Entrance
  64.     la $s3, encode1  #almaceno la direccion de encode1 en s3, s3 es el puntero
  65.     la $s4, encode2  #almaceno la direccion de encode2 en s4, s4 es el puntero
  66.     or $a3,$zero,$s3
  67.     or $a2,$zero,$s4
  68.  
  69. sig_carac:
  70.     lbu $s1, 0($s0)
  71.     beq $s1, $zero, fin   # Si es el carácter de final de cadena, ya terminamos
  72.     add $a0,$zero,$s1     # Pasando el primer parámetro a la función procesar()
  73.    
  74.     jal procesar          # Llamamos a la función procesar()
  75.     addiu $a1,$s0,1       # Pasando el segundo parámetro a la función procesar()
  76.    
  77.     add $a0,$zero,$s1  #El carácter en $a0
  78.     jal almacenar     # Llamamos a la función almacenar()
  79.     add $a1,$zero,$v0  # Ponemos el número de caracteres en $a1
  80.    
  81.     beq $zero,$zero,sig_carac  # Siguiente carácter diferente
  82.     or $s0, $zero, $v1        # Actualizamos el puntero con el valor devuelto
  83.  
  84. #
  85. # Exit
  86. #
  87. fin:
  88.  
  89.     jal almacenar_salida
  90.  
  91.     #Imprimir la matriz de salida codificada
  92.     # Número de syscall
  93.     ori $v0,$zero,4
  94.     # $a0 = buffer a imprimir
  95.     la $a0,encode
  96.     syscall
  97.  
  98.     jal decodificar
  99.  
  100.     #Imprimir la matriz de salida decodificada
  101.     # Número de syscall
  102.     ori $v0,$zero,4
  103.     # $a0 = buffer a imprimir
  104.     la $a0,decode
  105.     syscall
  106.  
  107.     ori $v0,$zero,10   # Terminamos con exit
  108.     syscall
  109.  
  110. #
  111. # Procesar (habría que poner un nombre más explicativo :)
  112. #
  113. # Recibe un carácter y el puntero a una cadena
  114. # Cuenta cuántos caracteres iguales al pasado consecutivos hay en la cadena
  115. # Devuelve en $v0 el número de caracteres iguales
  116. # y en $v1 el puntero al primer carácter diferente encontrado
  117. procesar:
  118.     add $v0, $zero, $zero   # Inicializamos valores de retorno
  119.     add $v1, $zero, $a1
  120.     add $t1, $zero, $zero   # Contador de caracteres iguales consecutivos
  121. procesar_iguales:
  122.     lbu $t0, 0($a1)                    # Cargamos el siguiente carácter a comparar
  123.     bne $a0, $t0, procesar_noiguales   # Si no son iguales, terminamos
  124.     addiu $a1, $a1, 1                  # Apuntamos al siguiente carácter    
  125.     beq $zero, $zero, procesar_iguales
  126.     addiu $t1, $t1, 1                  # Si son iguales, aumentamos el contador en uno
  127.  
  128. procesar_noiguales:
  129.     add $v0, $v0, $t1   # Ponemos los valores de retorno
  130.     add $v1, $v1, $t1
  131.  
  132.  
  133. # Volvemos de la función
  134.     jr $ra
  135.     nop
  136.  
  137.  
  138. almacenar:
  139.  
  140.     sb $a0,0($a3)   #meto el caracter en la primera direccion de a3
  141.     sb $a1,0($a2)   #meto el contador en la primera direccion de a4
  142.  
  143.     #avanzo el puntero
  144.  
  145.     addiu $a3,$a3,1
  146.     addiu $a2,$a2,1
  147.  
  148.  
  149.  
  150. # Volvemos de la función
  151.     jr $ra
  152.     nop
  153.  
  154. almacenar_salida:
  155.     la $a0,encode1
  156.     la $a1,encode2
  157.     la $a3,encode
  158.  
  159. while:
  160.  
  161.     beq $a0,$zero,finwhile    #si es el caracter vacio acabo
  162.     lbu $a3,0($a1)              #cargo el primer numero en encode
  163.     addiu $a3,$a3,1             #avanzo el puntero de encode
  164.     lbu $a3,0($a0)              #cargo el caracter en encode
  165.  
  166.     #avanzo todos los punteros
  167.     addiu $a3,$a3,1
  168.     addiu $a0,$a0,1
  169.     addiu $a1,$a1,1
  170.  
  171.     j while                   #llamo a while de nuevo
  172.  
  173.  
  174. finwhile:
  175.  
  176. # Volvemos de la función
  177.     jr $ra
  178.     nop
  179.  
  180.  
  181. decodificar:
  182.  
  183.     la $a0,encode1
  184.     la $a1,encode2
  185.     la $a3,decode
  186.  
  187. while2:
  188.  
  189.     beq $a0,$zero,finwhile2    #si es el caracter vacio acabo
  190.     lbu $a3,0($a0)             #cargo el caracter en decode
  191.     addiu $a3,$a3,1            #avanzo el puntero decode
  192.     addiu $a1,$a1,-1           #a1-1 #le resto 1 al primer numero
  193.     bnez $a1,while2            #repito el while2 si $a1 es distinto de 0
  194.  
  195.     #avanzo todos los punteros
  196.     addiu $a3,$a3,1
  197.     addiu $a0,$a0,1
  198.     addiu $a1,$a1,1
  199.  
  200.     j while2
  201.    
  202.  
  203.  
  204. finwhile2:
  205.  
  206. # Volvemos de la función
  207.     jr $ra
  208.     nop
  209.  

Ahora vayamos por partes, y a ver si estoy en el buen camino de lo que se me ha ocurrido:

Código: ASM
  1. #Almacenar el String en la matriz
  2. # Número de syscall
  3.     ori $v0,$zero,8
  4. # $a0 = buffer para guardar la cadena
  5.     la $a0,Entranceaux
  6. # $a1 = tamaño a leer
  7.     ori $a1,$zero,80
  8.     syscall
  9.  
  10. #quitar el ultimo caracter de entrance.
  11.  
  12. la $a0,Entrance         #Almaceno la entrada sin el caracter "enter"
  13. la $a1,Entranceaux      #Cadena de entrada
  14. la $a2,Entranceaux+1´   #puntero al segundo caracter de la cadena de entrada
  15.  
  16. recorrer:
  17.     beq $a2, $zero, imprimir
  18.     lbu $a0,0($a1)      #meto el caracter
  19.  
  20.     #avanzo todos los punteros
  21.     addiu $a2,$a2,1
  22.     addiu $a0,$a0,1
  23.     addiu $a1,$a1,1
  24.      
  25.     j recorrer
  26.  

Se me ha ocurrido almacenar la entrada por teclado en una matriz auxiliar, tener 2 punteros, uno que apunte al primer caracter de esta matriz, y otro al segundo. Si el segundo puntero apunta al caracter fin de cadena, se acaba, por lo tanto no me meterá el caracter intro.

Código: ASM
  1. almacenar_salida:
  2.     la $a0,encode1
  3.     la $a1,encode2
  4.     la $a3,encode
  5.  
  6. while:
  7.  
  8.     beq $a0,$zero,finwhile    #si es el caracter vacio acabo
  9.     lbu $a3,0($a1)              #cargo el primer numero en encode
  10.     addiu $a3,$a3,1             #avanzo el puntero de encode
  11.     lbu $a3,0($a0)              #cargo el caracter en encode
  12.  
  13.     #avanzo todos los punteros
  14.     addiu $a3,$a3,1
  15.     addiu $a0,$a0,1
  16.     addiu $a1,$a1,1
  17.  
  18.     j while                   #llamo a while de nuevo
  19.  
  20.  
  21. finwhile:
  22.  
  23. # Volvemos de la función
  24.     jr $ra
  25.     nop
  26.  

Al macenar la salida es como lo he puesto antes, pero en vez de jal, j porque no necesito almacenar la direccion de salto.

Código: ASM
  1.  
  2. decodificar:
  3.  
  4.     la $a0,encode1
  5.     la $a1,encode2
  6.     la $a3,decode
  7.  
  8. while2:
  9.  
  10.     beq $a0,$zero,finwhile2    #si es el caracter vacio acabo
  11.     lbu $a3,0($a0)             #cargo el caracter en decode
  12.     addiu $a3,$a3,1            #avanzo el puntero decode
  13.     addiu $a1,$a1,-1           #a1-1 #le resto 1 al primer numero
  14.     bnez $a1,while2            #repito el while2 si $a1 es distinto de 0
  15.  
  16.     #avanzo todos los punteros
  17.     addiu $a3,$a3,1
  18.     addiu $a0,$a0,1
  19.     addiu $a1,$a1,1
  20.  
  21.     j while2
  22.    
  23.  
  24.  
  25. finwhile2:
  26.  
  27. # Volvemos de la función
  28.     jr $ra
  29.     nop
  30.  

Y luego para decodificar, pues directamente, si el puntero a la matriz de caracter es el de final de cadena, acabo, si no, lo que hago es decrementar el primer numero de la matriz de numeros, y meter el caracter en la matriz final, avanzo el puntero de la matriz final, y vuelvo a hacer el while. Asi hasta que sea 0, entonces avanzo todos los punteros y otra vez a empezar.

Como te he dicho antes, obviamente no funciona, pero creo que la idea es esa, y creo que van por ahi los tiros, creo que no debo de tener fallos muy gordos, o al menos eso espero. Tu como lo ves?

Salu2

PD: luego me mandas tu direccion por privado, a la que quieres que te envie el jamon,  :lol:



m0skit0

  • Miembro de PLATA
  • *****
  • Mensajes: 2337
  • Nacionalidad: ma
    • Ver Perfil
    • http://fr33kk0mpu73r.blogspot.com/
Re: RLE en ensamblador MIPS
« Respuesta #61 en: Viernes 12 de Junio de 2009, 13:24 »
0
Bueno, vamos por pasos.

La verdad es que lo que has hecho de 2 buffers, copiar uno a otro, aparte de que está mal, no tiene mucho sentido utilizar Entranceaux. Aún así, el puntero a Entranceaux+1 sobra. Además, ¿para qué sumas 1 a a0 si tienes un carácter? Tienes que concentrarte un poco más en lo que estés haciendo...  :P

Yo como soy de funciones, voy a hacer una función que sustituya el carácter 0xA (el molesto enter) por un 0 (final de cadena :)):

Código: Text
  1. # void EliminarEnter(char* entrada)
  2. eliminar_enter:
  3.     li $t1,0xA
  4. ee_bucle:
  5.     lbu $t0,0($a0)
  6.     beq $t0,0xA,fin_ee
  7.     addiu $a0,$a0,1
  8.     beq $zero,$zero,ee_bucle
  9.     nop
  10. fin_ee:
  11.     jr $ra
  12.     sb $zero,-1($a0)
  13.  
Y para llamar a la función (evidente, pero lo pongo iwalmente):

Código: Text
  1. la $a0,entrance
  2. jal eliminar_enter
  3. nop
  4.  
Teniendo en cuenta que hemos guardado la cadena en entrance y no en entranceaux, que como ya te dije, sobra.

Otra cosilla: los while se hacen con instrucciones branch, no jump ;)

manurodri189

  • Miembro MUY activo
  • ***
  • Mensajes: 117
    • Ver Perfil
Re: RLE en ensamblador MIPS
« Respuesta #62 en: Viernes 12 de Junio de 2009, 13:44 »
0
Ok, gracias, pongo de nuevo todo el codigo, para que lo veas, y tener una copia de seguridad que nunca está demás  :lol:

Código: ASM
  1. .data
  2. Entrance: .space 80
  3. encode1: .space 40
  4. encode2: .space 40
  5. encode: .space 40
  6. decode: .space 80
  7. msg1: .asciiz "Please insert the String: "
  8. msg2: .asciiz " "
  9. msg3: .asciiz "n String encode like: "
  10. msg4: .asciiz "n String decode like: "
  11. .text
  12. .globl main
  13.  
  14. #
  15. # Main
  16. #
  17. main:
  18.     ori $v0,$zero,4
  19.     la $a0,msg1
  20.     syscall
  21.  
  22. #Almacenar el String en la matriz
  23. # Número de syscall
  24.     ori $v0,$zero,8
  25. # $a0 = buffer para guardar la cadena
  26.     la $a0,Entrance
  27. # $a1 = tamaño a leer
  28.     ori $a1,$zero,80
  29.     syscall
  30.  
  31. la $a0,Entrance
  32. jal eliminar_enter
  33. nop
  34.  
  35. #Imprimir la matriz
  36. # Número de syscall
  37.     ori $v0,$zero,4
  38. # $a0 = buffer a imprimir
  39.     la $a0,Entrance
  40.     syscall
  41.  
  42. #
  43. # Codificar
  44. #
  45. start:
  46.     la $s0, Entrance
  47.     la $s3, encode1  #almaceno la direccion de encode1 en s3, s3 es el puntero
  48.     la $s4, encode2  #almaceno la direccion de encode2 en s4, s4 es el puntero
  49.     or $a3,$zero,$s3
  50.     or $a2,$zero,$s4
  51.  
  52. sig_carac:
  53.     lbu $s1, 0($s0)
  54.     beq $s1, $zero, fin   # Si es el carácter de final de cadena, ya terminamos
  55.     add $a0,$zero,$s1     # Pasando el primer parámetro a la función procesar()
  56.    
  57.     jal procesar          # Llamamos a la función procesar()
  58.     addiu $a1,$s0,1       # Pasando el segundo parámetro a la función procesar()
  59.    
  60.     add $a0,$zero,$s1  #El carácter en $a0
  61.     jal almacenar     # Llamamos a la función almacenar()
  62.     add $a1,$zero,$v0  # Ponemos el número de caracteres en $a1
  63.    
  64.     beq $zero,$zero,sig_carac  # Siguiente carácter diferente
  65.     or $s0, $zero, $v1        # Actualizamos el puntero con el valor devuelto
  66.  
  67. #
  68. # Exit
  69. #
  70. fin:
  71.  
  72.     jal almacenar_salida
  73.  
  74.     #Imprimir la matriz de salida codificada
  75.     # Número de syscall
  76.     ori $v0,$zero,4
  77.     # $a0 = buffer a imprimir
  78.     la $a0,encode
  79.     syscall
  80.  
  81.     jal decodificar
  82.  
  83.     #Imprimir la matriz de salida decodificada
  84.     # Número de syscall
  85.     ori $v0,$zero,4
  86.     # $a0 = buffer a imprimir
  87.     la $a0,decode
  88.     syscall
  89.  
  90.     ori $v0,$zero,10   # Terminamos con exit
  91.     syscall
  92.  
  93. #
  94. # Procesar (habría que poner un nombre más explicativo :)
  95. #
  96. # Recibe un carácter y el puntero a una cadena
  97. # Cuenta cuántos caracteres iguales al pasado consecutivos hay en la cadena
  98. # Devuelve en $v0 el número de caracteres iguales
  99. # y en $v1 el puntero al primer carácter diferente encontrado
  100. procesar:
  101.     add $v0, $zero, $zero   # Inicializamos valores de retorno
  102.     add $v1, $zero, $a1
  103.     add $t1, $zero, $zero   # Contador de caracteres iguales consecutivos
  104. procesar_iguales:
  105.     lbu $t0, 0($a1)                    # Cargamos el siguiente carácter a comparar
  106.     bne $a0, $t0, procesar_noiguales   # Si no son iguales, terminamos
  107.     addiu $a1, $a1, 1                  # Apuntamos al siguiente carácter    
  108.     beq $zero, $zero, procesar_iguales
  109.     addiu $t1, $t1, 1                  # Si son iguales, aumentamos el contador en uno
  110.  
  111. procesar_noiguales:
  112.     add $v0, $v0, $t1   # Ponemos los valores de retorno
  113.     add $v1, $v1, $t1
  114.  
  115.  
  116. # Volvemos de la función
  117.     jr $ra
  118.     nop
  119.  
  120.  
  121. almacenar:
  122.  
  123.     sb $a0,0($a3)   #meto el caracter en la primera direccion de a3
  124.     sb $a1,0($a2)   #meto el contador en la primera direccion de a4
  125.  
  126.     #avanzo el puntero
  127.  
  128.     addiu $a3,$a3,1
  129.     addiu $a2,$a2,1
  130.  
  131.  
  132.  
  133. # Volvemos de la función
  134.     jr $ra
  135.     nop
  136.  
  137. almacenar_salida:
  138.     la $a0,encode1
  139.     la $a1,encode2
  140.     la $a3,encode
  141.  
  142. while:
  143.  
  144.     beq $a0,$zero,finwhile    #si es el caracter vacio acabo
  145.     lbu $a3,0($a1)              #cargo el primer numero en encode
  146.     addiu $a3,$a3,1             #avanzo el puntero de encode
  147.     lbu $a3,0($a0)              #cargo el caracter en encode
  148.  
  149.     #avanzo todos los punteros
  150.     addiu $a3,$a3,1
  151.     addiu $a0,$a0,1
  152.     addiu $a1,$a1,1
  153.  
  154.     b while                   #llamo a while de nuevo
  155.  
  156.  
  157. finwhile:
  158.  
  159. # Volvemos de la función
  160.     jr $ra
  161.     nop
  162.  
  163.  
  164. decodificar:
  165.  
  166.     la $a0,encode1
  167.     la $a1,encode2
  168.     la $a3,decode
  169.  
  170. while2:
  171.  
  172.     beq $a0,$zero,finwhile2    #si es el caracter vacio acabo
  173.     lbu $a3,0($a0)             #cargo el caracter en decode
  174.     addiu $a3,$a3,1            #avanzo el puntero decode
  175.     addiu $a1,$a1,-1           #a1-1 #le resto 1 al primer numero
  176.     bnez $a1,while2            #repito el while2 si $a1 es distinto de 0
  177.  
  178.     #avanzo todos los punteros
  179.     addiu $a3,$a3,1
  180.     addiu $a0,$a0,1
  181.     addiu $a1,$a1,1
  182.  
  183.     b while2
  184.    
  185.  
  186.  
  187. finwhile2:
  188.  
  189. # Volvemos de la función
  190.     jr $ra
  191.     nop
  192.  
  193. # void EliminarEnter(char* entrada)
  194. eliminar_enter:
  195.     li $t1,0xA
  196. ee_bucle:
  197.     lbu $t0,0($a0)
  198.     beq $t0,0xA,fin_ee
  199.     addiu $a0,$a0,1
  200.     beq $zero,$zero,ee_bucle
  201.     nop
  202. fin_ee:
  203.     jr $ra
  204.     sb $zero,-1($a0)
  205.  

He cambiado las j por b, como me has dicho que usa branches y no jumps. Pero sigue sin ir, es posible que la logica esté mal? o son las intrucciones? aunque creo que la lógica es la correcta. Muchas gracias.

Salu2



m0skit0

  • Miembro de PLATA
  • *****
  • Mensajes: 2337
  • Nacionalidad: ma
    • Ver Perfil
    • http://fr33kk0mpu73r.blogspot.com/
Re: RLE en ensamblador MIPS
« Respuesta #63 en: Viernes 12 de Junio de 2009, 13:58 »
0
Así a primera vista, te veo un error muy gordo: la instrucción que va después de los jal se ejecuta siempre, y la dirección de retorno es jal + 8, por tanto:

Código: Text
  1. fin:
  2.  
  3.     jal almacenar_salida
  4.  
  5.     #Imprimir la matriz de salida codificada
  6.     # Número de syscall
  7.     ori $v0,$zero,4
  8.     # $a0 = buffer a imprimir
  9.     la $a0,encode
  10.     syscall
  11.  
está mal, puesto que ori $v0,$zero,4 se ejecuta antes de jal almacenar_salida, y al volver de la función caes en la $a0,encode. Y así todos los siguientes.

manurodri189

  • Miembro MUY activo
  • ***
  • Mensajes: 117
    • Ver Perfil
Re: RLE en ensamblador MIPS
« Respuesta #64 en: Viernes 12 de Junio de 2009, 14:01 »
0
Ok, entiendo se me pasó poner nop detras de la instruccion, con uno seria suficiente, no?

Salu2

PD: sigue sin tirar.



m0skit0

  • Miembro de PLATA
  • *****
  • Mensajes: 2337
  • Nacionalidad: ma
    • Ver Perfil
    • http://fr33kk0mpu73r.blogspot.com/
Re: RLE en ensamblador MIPS
« Respuesta #65 en: Viernes 12 de Junio de 2009, 14:10 »
0
En

Código: Text
  1.     add $a0,$zero,$s1  #El carácter en $a0
  2.     jal almacenar     # Llamamos a la función almacenar()
  3.     add $a1,$zero,$v0  # Ponemos el número de caracteres en $a1
  4.  
Ten en cuenta que $v0 lleva el número de caracteres repetidos tras el primero leído, por tanto el número de caracteres iguales es $v0 + 1.

manurodri189

  • Miembro MUY activo
  • ***
  • Mensajes: 117
    • Ver Perfil
Re: RLE en ensamblador MIPS
« Respuesta #66 en: Viernes 12 de Junio de 2009, 14:14 »
0
Corregido de la siguiente maner:

Código: ASM
  1. add $a0,$zero,$s1  #El carácter en $a0
  2.     jal almacenar     # Llamamos a la función almacenar()
  3.     addiu $v0,$v0,1    #sumamos 1 a v0
  4.     add $a1,$zero,$v0  # Ponemos el número de caracteres en $a1
  5.  

Tiene que haber más errores. porque sucede lo mismo. Muchas gracias de verdad.

Salu2



m0skit0

  • Miembro de PLATA
  • *****
  • Mensajes: 2337
  • Nacionalidad: ma
    • Ver Perfil
    • http://fr33kk0mpu73r.blogspot.com/
Re: RLE en ensamblador MIPS
« Respuesta #67 en: Viernes 12 de Junio de 2009, 14:19 »
0
Cita de: "manurodri189"
Corregido de la siguiente maner:
:huh: Mal again: add $a1,$zero,$v0 no se ejecuta antes de saltar a la función, sino una vez ejecutada...  <_<

Cita de: "manurodri189"
Tiene que haber más errores
Sí, hay unos cuantos, pero sinceramente no te voy a hacer todo y me estoy cansando un poco... La de codificar funciona, así que vuelve a mirar las funciones que has hecho, sobre todo la de decodificar. Sólo tiene que hacer el proceso inverso a codificar, así que es sencillo. La vas a tener que hacer tú solito :brickwall:

PD: repites siempre los mismos errores, concéntrate en lo que haces y déjate de prisas  ;)

manurodri189

  • Miembro MUY activo
  • ***
  • Mensajes: 117
    • Ver Perfil
Re: RLE en ensamblador MIPS
« Respuesta #68 en: Viernes 12 de Junio de 2009, 14:45 »
0
Ok, tio la verdad es que llevas razon, pero aunque creo que le estoy cogiendo la dinamica a esto estoy un poco verdad, todavia.

Mira he actualizado asi, para que si se ejecute ese comando:

Código: ASM
  1. add $a0,$zero,$s1  #El carácter en $a0
  2.     addiu $v0,$v0,1    #sumamos 1 a v0
  3.     jal almacenar     # Llamamos a la función almacenar()
  4.     add $a1,$zero,$v0  # Ponemos el número de caracteres en $a1
  5.  

Debajo de la llamada a decodifcar, me ocurria lo mismo así que también he puesto un nop.

Me has dicho que codificar funciona, pero creo que el almacenamiento en encode, no porque lo imprimo y no hace nada.

También he puesto el nop debajo de beq, porque tambien consume 8 al igual que jal.

Código: ASM
  1. almacenar_salida:
  2.     la $a0,encode1
  3.     la $a1,encode2
  4.     la $a3,encode
  5.  
  6. while:
  7.  
  8.     beq $a0,$zero,finwhile    #si es el caracter vacio acabo
  9.     nop
  10.     lbu $a3,0($a1)              #cargo el primer numero en encode
  11.     addiu $a3,$a3,1             #avanzo el puntero de encode
  12.     lbu $a3,0($a0)              #cargo el caracter en encode
  13.  
  14.     #avanzo todos los punteros
  15.     addiu $a3,$a3,1
  16.     addiu $a0,$a0,1
  17.     addiu $a1,$a1,1
  18.  
  19.     b while                   #llamo a while de nuevo
  20.  
  21. finwhile:
  22.  
  23. # Volvemos de la función
  24.     jr $ra
  25.     nop
  26.  

Y en decodificar lo mismo.

Código: ASM
  1. decodificar:
  2.  
  3.     la $a0,encode1
  4.     la $a1,encode2
  5.     la $a3,decode
  6.  
  7. while2:
  8.  
  9.     beq $a0,$zero,finwhile2    #si es el caracter vacio acabo
  10.     nop
  11.     lbu $a3,0($a0)             #cargo el caracter en decode
  12.     addiu $a3,$a3,1            #avanzo el puntero decode
  13.     addiu $a1,$a1,-1           #a1-1 #le resto 1 al primer numero
  14.     bnez $a1,while2            #repito el while2 si $a1 es distinto de 0
  15.     nop
  16.    
  17.  
  18.     #avanzo todos los punteros
  19.     addiu $a3,$a3,1
  20.     addiu $a0,$a0,1
  21.     addiu $a1,$a1,1
  22.  
  23.     b while2
  24.  
  25. finwhile2:
  26.  
  27. # Volvemos de la función
  28.     jr $ra
  29.     nop
  30.  

La verdad es que no se por donde cogerlo, ten en cuenta que es mi primera vez, no digo que me lo hagas, si no un poco de ayuda, si no te importa, mas que nada para los conceptos, y luego yo localizo los errores y los intento arreglar, porque sigo pensando que estoy en la dinamica, o no?

Salu2

Edito: acabo de modifcar lo de la instruccion de debajo porque veo que lo uso en el bnez.



manurodri189

  • Miembro MUY activo
  • ***
  • Mensajes: 117
    • Ver Perfil
Re: RLE en ensamblador MIPS
« Respuesta #69 en: Viernes 12 de Junio de 2009, 14:56 »
0
Por cierto, por más que lo miro, sigo pensando que la lógica está bien, pero falla algo de Mips que no controlo.

Salu2



m0skit0

  • Miembro de PLATA
  • *****
  • Mensajes: 2337
  • Nacionalidad: ma
    • Ver Perfil
    • http://fr33kk0mpu73r.blogspot.com/
Re: RLE en ensamblador MIPS
« Respuesta #70 en: Viernes 12 de Junio de 2009, 15:00 »
0
Cita de: "manurodri189"
Me has dicho que codificar funciona, pero creo que el almacenamiento en encode, no porque lo imprimo y no hace nada.
Funciona bien codificar y almacenar. Míra los valores en la memoria. Por tanto tienes mal el procedimiento de impresión.

Cita de: "manurodri189"
También he puesto el nop debajo de beq, porque tambien consume 8 al igual que jal.
Todos los saltos son así.

¿Qué tal si me pones qué debes hacer para descodificar? En pseudocódigo, para ver.

manurodri189

  • Miembro MUY activo
  • ***
  • Mensajes: 117
    • Ver Perfil
Re: RLE en ensamblador MIPS
« Respuesta #71 en: Viernes 12 de Junio de 2009, 15:09 »
0
Ok, a ver si escribo bien el pseudocodigo:

Código: Text
  1. Mientras encode1 no sea fin de cadena.
  2.      
  3.      meter el primer caracter de encode1 en decode.
  4.      avanzar el puntero de decode
  5.      restar 1 al primer numero de encode2   (porque ya hemos metido un caracter en el resultado)
  6.      si el primer numero de encode2 es cero
  7.             avanzar los punteros, encode1, encode2 y decode
  8. repetir
  9. fin mientras.
  10.  

Es esto lo que quiero que haga, y creo que el procedimiento en mips es el correcto, no? creo que lo que tiene que fallar es algo de intrucciones.

Por cierto como es que hago mal el proceso de impresion?

Salu2



m0skit0

  • Miembro de PLATA
  • *****
  • Mensajes: 2337
  • Nacionalidad: ma
    • Ver Perfil
    • http://fr33kk0mpu73r.blogspot.com/
Re: RLE en ensamblador MIPS
« Respuesta #72 en: Viernes 12 de Junio de 2009, 17:16 »
0
Intenta usar sólo los registros $aX (preferiblemente sólo lectura) y $tX (puedes hacer con ellos lo que quieras) dentro de las funciones  ;)

Primero, se supone que el número de elementos de encode1 y encode2 es el mismo, y no vamos a verificar esto. Resumidamente: por cada carácter de encode1, escribirlo en decode tantas veces veces como indique el elemento correspondiente en encode2. El pseudo-código sería por tanto:

Código: Text
  1. Cargamos dirección de "encode1", "encode2" y "decode"
  2. Cargamos carácter de "encode1" y avanzamos puntero
  3. Mientras no sea fin de cadena
  4.     Cargamos número de caracteres de "encode2" y avanzamos puntero
  5.     Mientras número de caracteres sea distinto de 0
  6.         Escribe carácter en decode y avanza puntero
  7.         Restar 1 al número de caracteres
  8.     Repetir
  9.     Cargamos carácter de "encode1" y avanzamos puntero
  10. Repetir
  11.  

manurodri189

  • Miembro MUY activo
  • ***
  • Mensajes: 117
    • Ver Perfil
Re: RLE en ensamblador MIPS
« Respuesta #73 en: Viernes 12 de Junio de 2009, 20:14 »
0
A ver que te parece la funcion:

Código: ASM
  1. decodificar:
  2.  
  3.     la $a0,encode1
  4.     la $a1,encode2
  5.     la $a3,decode
  6.     lbu $a3,0($a0)             #cargo el caracter en decode
  7.     addiu $a3,$a3,1            #avanzo el puntero decode
  8.  
  9. while2:
  10.  
  11.     beq $a0,$zero,finwhile2    #si es el caracter vacio acabo
  12.     nop
  13.     lbu $a2,0($a1)             #cargo el numero
  14.     addiu $a1,$a1,1            #avanzo el puntero
  15.  
  16. while3:
  17.  
  18.     beq $a2,$zero,etiqueta   #salto a etiqueta si es igual a 0
  19.     nop
  20.    
  21.     lbu $a3,0($a0)             #cargo el caracter en decode
  22.     addiu $a3,$a3,1            #avanzo el puntero decode
  23.     addiu $a2,$a2,-1           #a2-1 #le resto 1 al primer numero
  24.  
  25.     b while3
  26.  
  27. etiqueta:
  28.  
  29.     lbu $a3,0($a0)             #cargo el caracter en decode
  30.     addiu $a3,$a3,1            #avanzo el puntero decode
  31.  
  32.     b while2
  33.  
  34. finwhile2:
  35.  
  36. # Volvemos de la función
  37.     jr $ra
  38.     nop
  39.  

Pero creo que si mal no he entendido, que tendria que restar uno al contador ya que ya he metido uno a la matriz decode antes de entrar a los while, no es asi?.

Salu2



m0skit0

  • Miembro de PLATA
  • *****
  • Mensajes: 2337
  • Nacionalidad: ma
    • Ver Perfil
    • http://fr33kk0mpu73r.blogspot.com/
Re: RLE en ensamblador MIPS
« Respuesta #74 en: Sábado 13 de Junio de 2009, 15:30 »
0
:huh:  :P

Sigues haciendo los mismos errores <_< . Cargas punteros y los usas como caracteres, especificas mal las entradas de función (y eso que ni siquiera estamos usando la pila :P), te haces un lío con los registros, lees en vez de escribir en memoria, te olvidas de que la instrucción siguiente a los saltos se ejecuta antes que el salto (y eso que lo acabamos de hablar :P ). Las instrucciones están bien planteadas, pero tienes que estar más al loro de que estás haciendo mal. No hacer lo primero que se te ocurra, probarlo, y si no funciona, esperar a que yo te ponga la corrección. Si no funciona, mira a ver por qué, ejecuta paso a paso y ve viendo qué hace tu código y cómo debería hacerlo en realidad. Así es como realmente se aprende, y sí, aprender requiere un esfuerzo  :brickwall:

A ver, primero vamos a suponer que la función es (estilo C, que mola más  B) ): void decodificar(const char* caracteres, const BYTE* frecuencias, const char* cadena_decodificada), siendo evidentemente caracteres = encode1 cargado en $a0, frecuencias = encode2 cargado en $a1, cadena_decodificada = decode cargado en $a2, y no devuelve ningún valor (void), así que no hace falta cargar $v0 (el registro en el que ponen el valor de retorno) con ningún valor. Estos parámetros los recibe la función cuando empieza, y trabaja suponiendo que están bien cargados antes de ser llamada. decodificar() es una función, por tanto los parámetros se le pasan y no hay que cargarlos. Así si queremos utilizar la función con otros parámetros no tenemos que modificar la función en sí (aunque esto creo que ya lo he dicho... :D ). Espero haberme explicado mejor esta vez sobre cómo crear y usar funciones en ensamblador MIPS  ^_^

Por tanto el inicio de la función tendría que ser directamente la carga del primer carácter de encode1 (o caracteres como definimos en C), que debe estar ya cargado en $a0. Además fíjate que caracteres y frecuencias están definidos como const en el prototipo de la función, así que no debemos modificar esas cadenas. Aparte, tampoco es necesario modificar los valores de los registros $aX, así que los usaremos sólo para leer (como te indiqué en el post anterior).

Código: Text
  1. decodificar:
  2.     # cargamos los parámetros en otros registros
  3.     or $t0,$zero,$a0   # encode1
  4.     or $t1,$zero,$a1   # encode2
  5.     or $t2,$zero,$a2   # decode
  6.  
Cargamos cada $aX en su $tX correspondiente, así no tenemos que modificar los $aX para nada, y podemos decir que nuestra función mantiene esos registros sin modificar.
       
Código: Text
  1.     lbu $t3,0($t0)  # Carácter de "encode1" -> T3    
  2.     addiu $t0,$t0,1  # Avanzamos puntero
  3.  
Cargamos el carácter del puntero móvil de encode1 a $t3.

Código: Text
  1. decod_while1:    
  2.     beq $t3,$zero,fin_dec_while1  # Mientras no sea fin de cadena
  3.     nop
  4.     lbu $t4, 0($t1)  # Número de repeticiones del carácter
  5.     addiu $t1,$t1,1  # Avanzamos de elemento
  6.  
Aquí vamos recorriendo los carácteres de encode1 hasta encontrar el carácter de fin de cadena 0.

Código: Text
  1. decode_while2:
  2.     beq $t4,$zero,fin_dec_while2  # Mientras el número de caracteres no sea cero
  3.     nop
  4.     sb $t3, 0($t2)   # Escribimos el carácter en decode
  5.     addiu $t2,$t2,1  # Avanzamos el puntero móvil de decode
  6.     beq $zero,$zero dec_while2  # Repetimos
  7.     addiu $t4,$t4,-1  # Restamos uno al número de caracteres
  8.  
Mientras queden repeticiones, escribimos el caracter consecutivamente en la cadena decode.
   
Código: Text
  1. fin_dec_while2:    
  2.     lbu $t3,0($t0)  # Carácter de "encode1" -> T3    
  3.     beq $zero,$zero,decode_while1
  4.     addiu $t0,$t0,1  # Avanzamos puntero
  5.  
Siguiente carácter de encode1

Código: Text
  1. fin_dec_while1:
  2.     sb $zero, 0($t2)   # Escribimos el carácter de fin de cadena
  3.     jr $ra
  4.     nop
  5.  
No hay que olvidar poner un final de cadena en decode, porque si no no es una cadena de caracteres válida ;)

No lo he probado, hazlo tú (ve paso a paso y fíjate bien los valores que hay en memoria y los registros), y asegúrate de que le pasas bien los parámetros a la función en los registros $aX.

Si puedes decirme dónde fallaba tu código, estaría bien también, así analizas qué has hecho mal.

 :hola: