SoloCodigo

Programación General => ASM (Ensamblador) => Mensaje iniciado por: manurodri189 en Miércoles 20 de Mayo de 2009, 14:35

Título: RLE en ensamblador MIPS
Publicado por: manurodri189 en Miércoles 20 de Mayo de 2009, 14:35
Pues eso necesito saber si alguno de vosotros sabe de ensamblador y me puede echar una mano.

Tengo que hacer un codificador y un decodificador, según el algoritmo RLE

http://es.wikipedia.org/wiki/RLE (http://es.wikipedia.org/wiki/RLE" onclick="window.open(this.href);return false;)

Tiene que ser con MIPS, con el simulador PCSpim.

Tengo la certeza de que es realmente sencillo pero no se por donde puedo cogerlo.

A ver si alguno de vosotros me puede echar una mano.

Salu2
Título: Re: RLE en ensamblador MIPS
Publicado por: m0skit0 en Miércoles 20 de Mayo de 2009, 16:24
Yo sé MIPS, te puedo ayudar (que no hacer), pero tienes que especificar más el algoritmo. Por ejemplo, ¿qué pasa si el valor es un número?

A codificar:

Código: Text
  1. 22222AA
  2.  
Codificado:

Código: Text
  1. 522A
  2.  
¿5 "2" & 2 "A" / 522 "A"?
Título: Re: RLE en ensamblador MIPS
Publicado por: manurodri189 en Miércoles 20 de Mayo de 2009, 16:32
Si es como has puesto.

Si le pasas el valor22222AA tendría que devolver 522A.

No quiero que me lo hagas, pero realmente no tengo ni idea, así que necesitaría ayuda.

Salu2
Título: Re: RLE en ensamblador MIPS
Publicado por: m0skit0 en Miércoles 20 de Mayo de 2009, 16:34
Cita de: "manurodri189"
Si le pasas el valor22222AA tendría que devolver 522A.
Muy bien, pero la pregunta es, si tengo que descodificar, ¿cómo sé que 522A es "22222AA" y no "A" 522 veces?
Título: Re: RLE en ensamblador MIPS
Publicado por: manurodri189 en Miércoles 20 de Mayo de 2009, 18:39
Acabo de preguntarlo, y me acaba de responder lo siguiente:

Well, i can think of a few solutions:
> a) it can be a matter of what characters are valid: that is,
> we can assume that only letters can be encoded. So '2' as char is not valid.
> However, this is a dummy solution...
>
> b) it depends on the data structures you use. For instance,
> if you use 1 integer (3 bytes) to represent the number and
> 1 byte for the char, then you may have the following organization in memory:
>
> for each 4 consecutive bytes :
>
> [1 byte] [3 bytes] :
> [char] [integer]
>
>
> So , in your example, each byte would be :
>
> 32, 00 00 00 05
> 41, 00 00 00 02
>
>
> where, 32 is the ascii of '2'
> and 41 is the ascii of 'A'
>
>
> c) another solution is to keep all the chars together,
> in consecutive bytes and all the numbers together
> in a second array, where each integer is 4 bytes.
>
> So, for your example, you can define one array symbols:
> '2','A',...
> or with their ascii: 32,41,...
> and another array with their frequency:
> 5, 2, ...
> where each integer occupies 4 bytes.
>
> When your decode, you know that the first number corresponds to
>
>
> the first char, and so on,....
> (a) is too limited...
> I would prefer you do either b) or c), and I think c) is the easiest.

Osea la a, que tiene pinta de ser la más fácil descartada, la b la entiendo pero el dice que es la más difícil, y la c, no la entiendo.

Tu como lo ves? si no sabes ingles, me lo dices y te lo traduzco.

Salu2
Título: Re: RLE en ensamblador MIPS
Publicado por: m0skit0 en Jueves 21 de Mayo de 2009, 10:34
La a) es una cutrería, no me extraña que sea descartada. La b) y la c) son más adecuadas, pero no me parece que una sea más difícil que la otra.

La c), que no entiendes, lo que pretende es primero poner todos los caracteres diferentes seguidos y luego todos las frecuencias seguidas, en vez de intercalarlas.

Bueno, ahora decides tú cuál de las dos vas a preferir.

Saludos
Título: Re: RLE en ensamblador MIPS
Publicado por: manurodri189 en Jueves 21 de Mayo de 2009, 14:25
Ok, si crees que la dificultad es la misma prefiero la b, que creo que es más correcta, y entiendo mejor.

Por cierto, se me olvidó mencionar, que no es necesario hacer 2 programas, con uno que codifique y decodifique seria suficiente. Osea la entrada seria esta:

22222AA

Y la salida esta:

522A
22222AA

Muchas gracias por ayudarme y aconsejarme tío, es muy importante para mi.

Salu2
Título: Re: RLE en ensamblador MIPS
Publicado por: m0skit0 en Jueves 21 de Mayo de 2009, 15:58
Bueno, yo preferiría hacer 2 programas por separado, luego ya podrás usarlos como subrutinas de otro principal  ;)

¿Cómo crees que sería el algoritmo de codificación? En pseudo-código, por ejemplo.
Título: Re: RLE en ensamblador MIPS
Publicado por: manurodri189 en Jueves 21 de Mayo de 2009, 16:14
Pero en pseudocódigo es muy muy diferente, no? soy capaz de hacerlo en java, y no tardo mucho, si quieres lo hago para que veas que he captado la idea, pero no se de que puede servir eso, explicaté no lo entiendo, o es un pseudocódigo orientado a ensamblador?

Salu2

PD: por cierto tu mandas, si dices que 2 subrutinas por separado y un programa principal que es lo que ves mejor, pues así.
Título: Re: RLE en ensamblador MIPS
Publicado por: m0skit0 en Jueves 21 de Mayo de 2009, 16:56
Cita de: "manurodri189"
soy capaz de hacerlo en java, y no tardo mucho
Con eso me vale. Pero tampoco voy a hacerlo yo, como puedes entender. Y si sabes hacerlo en Java, alguna idea tendrás de cómo empezarlo en MIPS.

Cita de: "manurodri189"
por cierto tu mandas
Aquí no manda nadie, estamos para ayudar  ^_^
Título: Re: RLE en ensamblador MIPS
Publicado por: manurodri189 en Jueves 21 de Mayo de 2009, 17:06
Ok, me llevara un tiempecito, porque también estoy liado con otra cosa, así que en un par de días o así postearé el código en java. Pero vamos de Mips lo que se dice Mips ni idea.

Salu2
Título: Re: RLE en ensamblador MIPS
Publicado por: m0skit0 en Jueves 21 de Mayo de 2009, 18:03
Cita de: "manurodri189"
Pero vamos de Mips lo que se dice Mips ni idea.
Pues ya sabes lo que toca: ponerse a estudiar. Te puedes ahorrar el código en Java, pues como te he dicho, no te lo voy a traducir a MIPS. En todo caso te ayudaría con las dudas, o bien si controlas otro ensamblador, digamos x86, también podríamos ver. Pero si no tienes ni idea de ensamblador... mal vamos.

Un saludo
Título: Re: RLE en ensamblador MIPS
Publicado por: manurodri189 en Lunes 1 de Junio de 2009, 11:44
Vamos a ver, ahora que he acabado lo demás me he puesto con esté ejercicio.

Primero lo que he decidido es que se introduzca la cadena por teclado, y la codificación se haga de esta manera:

Si se introduce la cadena "22222AA"

Pues se codifica como un array que contenga [2 A] y otro que contenga el numero de repeticiones [5 2]. Esto creo que serviria.

Ahora me he puesto con el codigo pero necesito ayuda, porque es que me cuesta la vida.

He empezado con esto:

Código: ASM
  1. .data
  2. Entrance: .space 80
  3. encode1: .space 40
  4. encode2: .space 40
  5. decode: .space 80
  6. msg1: .asciiz "Please insert the String: "
  7. msg2: .asciiz " "
  8. msg3: .asciiz "n String encode like: "
  9. msg4: .asciiz "n String decode like: "
  10. .text
  11. .globl main
  12.  
  13. main:
  14.  
  15. in:
  16. li $v0,4
  17. la $a0,msg1
  18. syscall
  19. li $v0,8
  20. syscall
  21. li $v0,4
  22. syscall
  23.  

Se supone que en $v0 tengo la cadena que he introducido por teclado no?

Lo que quiero es separar la cadena por caracteres, coger el primer carcter meterlo en el array encode1 y compararlo con el siguiente, y si es igual lo saco de la supuesta array auxiliar e incremento un contador, y si es distinto, lo saco del array y pongo el contador en el array encode2. Tiene buena pinta no?

Pues bueno el primer paso seria comparar los caracteres de la cadena que tengo supuestamente en $v0, dame una idea de como hacerlo por favor.

Salu2
Título: Re: RLE en ensamblador MIPS
Publicado por: m0skit0 en Lunes 1 de Junio de 2009, 12:22
A ver, primero... ¿Estás usando un simulador de MIPS (PCSPIM ¿?), o cómo? Porque entonces tienes que explicarme qué hace cada syscall, o postear la documentación del manejador de excepciones, que no soy adivino  :D
Título: Re: RLE en ensamblador MIPS
Publicado por: manurodri189 en Lunes 1 de Junio de 2009, 12:27
Si uso PCSPIM, a ver tengo esto:

Código: ASM
  1. # la $a0,msg1
  2. # syscall
  3.  
  4. # li $v0,8
  5. # syscall
  6.  
  7. # li $v0,4
  8. # syscall
  9.  

La primera lo que hace es que me imprime el msg1 en la consola.
La segunda me captura por teclado un String.
Y la tercer me imprime un String en la consola.

syscall es una llamada al sistema, que por lo que veo, lo que hace depende de la sentencia anterior.

Salu2
Título: Re: RLE en ensamblador MIPS
Publicado por: m0skit0 en Lunes 1 de Junio de 2009, 12:49
Cita de: "manurodri189"
syscall es una llamada al sistema, que por lo que veo, lo que hace depende de la sentencia anterior.
Bueno, te aclaro. syscall no hace lo que dice la sentencia anterior. Funciona así: http://www.inf.pucrs.br/~eduardob/disci ... codes.html (http://www.inf.pucrs.br/~eduardob/disciplinas/arqi/mips/syscall_codes.html" onclick="window.open(this.href);return false;)

Volviendo a tu código, generalmente se pone la sección de datos depués de la de texto (código), pero bueno, no importa. Para leer una cadena, fíjate en la tabla la llamada número 8. Debes poner en $a0 la dirección del buffer y en $a1 en número de caracteres que se van a leer + 1, algo que no haces, y que vendría a ser:

Código: Text
  1. # Número de syscall
  2. ori $v0,$zero,8
  3. # $a0 = buffer para guardar la cadena
  4. la $a0,Entrance
  5. # $a1 = tamaño a leer
  6. ori $a1,$zero,80
  7. syscall
  8.  
Ahora ya tienes almacenada la cadena (máximo 80 caracteres) en Entrace. Para imprimirla, es el syscall 4 con la dirección de la cadena en $a0, por tanto:

Código: Text
  1. # Número de syscall
  2. ori $v0,$zero,4
  3. # $a0 = buffer a imprimir
  4. la $a0,Entrance
  5. syscall
  6.  

Cita de: "manurodri189"
Tiene buena pinta no?
:good:
Título: Re: RLE en ensamblador MIPS
Publicado por: manurodri189 en Lunes 1 de Junio de 2009, 16:55
Muchas gracias, la verdad es que no me ha costado entender tu codigo. Lo unico que tu usas un ori entre el registro $zero y el numero, supongo que $zero contiene todos ceros, no? asi al hacer un or logico inmediato con el numero, te lo guarda ya en el registro $v0, no es asi? yo usaba la sentencia li entre el registro y el numero, vamos que supongo que es lo mismo.

Ahora se supone que en Entrance, tengo el String, no es asi? pero para acceder al primer elemento del string, puedo acceder a el inmediatamente o tengo que hacer un desplazamiento asi, osea:

un dll, registro1, Entrance,2, o algo asi? Muchas gracias.

Salu2
Título: Re: RLE en ensamblador MIPS
Publicado por: m0skit0 en Lunes 1 de Junio de 2009, 17:49
Cita de: "manurodri189"
yo usaba la sentencia li entre el registro y el numero, vamos que supongo que es lo mismo.
Bueno, li es una pseudoinstrucción, es decir, realmente no existe como tal, sino que se traduce en 2 instrucciones: lui + ori. Si te fijas en el código que ejecuta el SPIM lo verás. De todas formas, no importa mucho, hazlo como mejor te venga, aunque es útil practicar con varias formas porque así se coge más soltura con ensamblador  ;)

Cita de: "manurodri189"
Ahora se supone que en Entrance, tengo el String, no es asi?
Sí señor  ^_^ después del primer syscall que puse.

Cita de: "manurodri189"
pero para acceder al primer elemento del string, puedo acceder a el inmediatamente o tengo que hacer un desplazamiento asi
No, para el primer elemento no debes hacer ningún desplazamiento. Entrance es un puntero al primer carácter de la cadena. Puedes acceder a él así, por ejemplo:

Código: Text
  1. # Puntero de cadena a $s0
  2. la $s0,Entrance
  3. # Cargamos el primer carácter en $s0
  4. lw $t0,0($s0)
  5.  
Ojo, si tienes puesto el "delayed load" como opción en el PCSPIM, el registro destino de las instrucciones load (lw, lb, etc...) tardará una instrucción más en cargarse. Con poner un nop después del load lo apañas.

Para ir accediendo a todos los caracteres de la cadena, es bastante fácil (supondré que no hay "delayed load", pero sí "delayed jump"):

Código: Text
  1. start:
  2. la $s0, Entrance  
  3. sig_carac:
  4. lw $t0, 0($s0)
  5. beq $t0, $zero, fin   # Si es el carácter de final de cadena, ya terminamos
  6. nop
  7. la procesar,$v0
  8. jal $v0               # Si no, llamamos a la función procesar()
  9. add $a0,$zero,$t0     # Pasando el primer parámetro a la función procesar()
  10. beq $zero,$zero,sig_carac  # Siguiente carácter
  11. addiu $s0,$s0,1            # Apuntamos al siguiente carácter
  12. fin:
  13. nop
  14.  
  15. procesar:
  16. [...]
  17. # Volvemos de la función
  18. jr $ra
  19. nop
  20.  
PD: todo esto lo escribo ahora de pasada, está sin probar, así que si falla algo, dímelo  :P
Título: Re: RLE en ensamblador MIPS
Publicado por: manurodri189 en Lunes 1 de Junio de 2009, 18:58
A ver como el código lo has comentado, no he tenido problema en entenderlo, además asi se entiende bastante facil.

He probado el codigo, pero en procesar de momento quiero que me imprima un blanco entre caracteres.

Por ejemplo la entrada es: "aabb"

y quiero que me imprima: "a a b b"

Más que nada para probarlo y entenderlo todo bien.

Este es el codigo que llevamos hasta ahora:

Código: ASM
  1. .data
  2. Entrance: .space 80
  3. encode1: .space 40
  4. encode2: .space 40
  5. decode: .space 80
  6. msg1: .asciiz "Please insert the String: "
  7. msg2: .asciiz " "
  8. msg3: .asciiz "n String encode like: "
  9. msg4: .asciiz "n String decode like: "
  10. .text
  11. .globl main
  12.  
  13. main:
  14.  
  15. in:
  16.  
  17. li $v0,4
  18. la $a0,msg1
  19. syscall
  20.  
  21. #Almacenar el String en la matriz
  22. # Número de syscall
  23. ori $v0,$zero,8
  24. # $a0 = buffer para guardar la cadena
  25. la $a0,Entrance
  26. # $a1 = tamaño a leer
  27. ori $a1,$zero,80
  28. syscall
  29.  
  30. #Imprimir la matriz
  31. # Número de syscall
  32. ori $v0,$zero,4
  33. # $a0 = buffer a imprimir
  34. la $a0,Entrance
  35. syscall
  36.  
  37. start:
  38. la $s0, Entrance  
  39. sig_carac:
  40. lw $t0, 0($s0)
  41. beq $t0, $zero, fin   # Si es el carácter de final de cadena, ya terminamos
  42. nop
  43. #la procesar,$v0
  44. #jal $v0               # Si no, llamamos a la función procesar()
  45. jal procesar
  46. add $a0,$zero,$t0     # Pasando el primer parámetro a la función procesar()
  47. beq $zero,$zero,sig_carac  # Siguiente carácter
  48. addiu $s0,$s0,1            # Apuntamos al siguiente carácter
  49. fin:
  50. nop
  51.  
  52. procesar:
  53.  
  54.  
  55. #Número de syscall
  56. ori $v0,$zero,4
  57. syscall
  58.  
  59. li $v0,4
  60. la $a0,msg2
  61. syscall
  62.  
  63. # Volvemos de la función
  64. jr $ra
  65. nop
  66.  

Pues bien lo que da a la salida es otra cosa:

aabb      (Esto lo hace bien porque se lo he puesto arriba)
aabb
 (null)

Porque puede ser? Muchas gracias de nuevo.

Salu2
Título: Re: RLE en ensamblador MIPS
Publicado por: m0skit0 en Lunes 1 de Junio de 2009, 20:30
:no: me parece que no has entendido cómo funcionan las llamadas al sistema con syscall...

Código: Text
  1. procesar:
  2. #Número de syscall
  3. ori $v0,$zero,4
  4. syscall
  5.  
  6. li $v0,4
  7. la $a0,msg2
  8. syscall
  9.  
  10. # Volvemos de la función
  11. jr $ra
  12. nop
  13.  
Esto es lo que has puesto en la función procesar. Ten en cuenta que los registros $aX se usan para pasar los parámetros a la función, siendo $a0 el primer parámetro, $a1 el segundo, etc... Pues nuestra función procesar recibe un solo parámetro, en $a0 como hemos dicho, y es el carácter (cuando hacemos add $a0,$zero,$t0 copiamos $t0 en $a0, y $t0 tiene el carácter que estamos procesando). Ahora, al hacer:

Código: Text
  1. ori $v0,$zero,4
  2. syscall
  3.  
al entrar en la función procesar, ¿qué estás haciendo? La llamada al sistema 4 imprime un cadena de caracteres, cuyo puntero es $a0. Pero en $a0... ¡¡tenemos un carácter (el código ASCII del carácter)!!. Y claro, en esa dirección de memoria no hay nada, por tanto no imprime nada  :P Y luego imprimes msg2 que es un espacio. Ahora la cuestión es ¿cómo imprimir un solo carácter si la única función que tenemos es para imprimir cadenas? No olvides que las cadenas acaban con un carácter nulo...
Título: Re: RLE en ensamblador MIPS
Publicado por: manurodri189 en Martes 2 de Junio de 2009, 18:58
Antes de nada una pregunta, en $a0 tengo el primer caracter, para compararlo con el siguiente solamente tendría que compararlo con Entrance, que se supone que ya esta apuntando ahi, cierto?

Esto ya lo he entendido:

Citar
al entrar en la función procesar, ¿qué estás haciendo? La llamada al sistema 4 imprime un cadena de caracteres, cuyo puntero es $a0. Pero en $a0... ¡¡tenemos un carácter (el código ASCII del carácter)!!. Y claro, en esa dirección de memoria no hay nada, por tanto no imprime nada :P Y luego imprimes msg2 que es un espacio.

Es como la etiqueta msg1, ya que msg1 es lo que almacenamos en $a0, y lo me me imprime es el mensaje, ya que msg1 apunta al mensaje, facil.

Pero lo de imprimir un solo caracter no sabria hacerlo, aunque en realidad no me vale para este ejercicio era solo para toquetear.

He continuado con el ejercicio a ver que tal:

Código: ASM
  1. procesar:
  2.  
  3. beq $a0,Entrance, counter #si es igual incremento el contador $a1 y vamos a sig_caract
  4. nop
  5. #meter el caracter en encode1 $si es diferente
  6. #meter el contador en encode2
  7. jal sig_caract
  8.  
  9. # Volvemos de la función
  10. jr $ra
  11. nop
  12.  
  13. counter:
  14. addi $a1,$a1,1
  15. jal sig_caract
  16.  

Que tal pinta tiene esto? aunque no se meter el caracter en la matriz y que me respente lo que haya, osea si me viene una a, meterlo y si despues viene una b, volverlo a meter, y que en encode 1 tenga "ab" o "a b" o algo asi. Muchas gracias.

Salu2
Título: Re: RLE en ensamblador MIPS
Publicado por: manurodri189 en Martes 2 de Junio de 2009, 19:45
La comparacion no seria con entrance seria con $s0, ya que es el puntero al siguiente caracter, cierto? osea esta linea:

Código: ASM
  1. beq $a0,$s0, counter
  2.  

Salu2
Título: Re: RLE en ensamblador MIPS
Publicado por: m0skit0 en Miércoles 3 de Junio de 2009, 10:12
Cita de: "manurodri189"
en $a0 tengo el primer caracter, para compararlo con el siguiente solamente tendría que compararlo con Entrance
Cita de: "manurodri189"
La comparacion no seria con entrance seria con $s0
Nop, tampoco  :P En $s0 tienes un puntero a un carácter, y en $a0 tienes un carácter. Tendrías que cargar el carácter en algún registro para compararlo. Lo que te aconsejo es que pases $s0 como parámetro a la función procesar():

Código: Text
  1. .data
  2. Entrance: .space 80
  3. encode1: .space 40
  4. encode2: .space 40
  5. decode: .space 80
  6. msg1: .asciiz "Please insert the String: "
  7. msg2: .asciiz " "
  8. msg3: .asciiz "n String encode like: "
  9. msg4: .asciiz "n String decode like: "
  10. .text
  11. .globl main
  12.  
  13. #
  14. # Main
  15. #
  16. main:
  17.     ori $v0,$zero,4
  18.     la $a0,msg1
  19.     syscall
  20.  
  21. #Almacenar el String en la matriz
  22. # Número de syscall
  23.     ori $v0,$zero,8
  24. # $a0 = buffer para guardar la cadena
  25.     la $a0,Entrance
  26. # $a1 = tamaño a leer
  27.     ori $a1,$zero,80
  28.     syscall
  29.  
  30. #Imprimir la matriz
  31. # Número de syscall
  32.     ori $v0,$zero,4
  33. # $a0 = buffer a imprimir
  34.     la $a0,Entrance
  35.     syscall
  36.  
  37. #
  38. # Codificar
  39. #
  40. start:
  41.     la $s0, Entrance  
  42. sig_carac:
  43.     lw $t0, 0($s0)
  44.     beq $t0, $zero, fin   # Si es el carácter de final de cadena, ya terminamos
  45.     add $a0,$zero,$t0     # Pasando el primer parámetro a la función procesar()
  46.     jal procesar  # Si no, llamamos a la función procesar()
  47.     addiu $a1,$s0,1    # Pasando el segundo parámetro a la función procesar()
  48.     beq $zero,$zero,sig_carac  # Siguiente carácter
  49.     addiu $s0,$s0,1            # Apuntamos al siguiente carácter
  50.  
  51. #
  52. # Exit
  53. #
  54. fin:
  55.     ori $v0,$zero,10   # Terminamos con exit
  56.     syscall
  57.  
  58. #
  59. # Procesar (habría que poner un nombre más explicativo :)
  60. #
  61. # Recibe un carácter y el puntero a una cadena
  62. # Cuenta cuántos caracteres iguales al pasado consecutivos hay en la cadena
  63. # Devuelve en $v0 el número de caracteres iguales
  64. # y en $v1 el puntero al primer carácter diferente encontrado
  65. procesar:
  66.     addiu $v0, $zero, $zero   # Inicializamos valores de retorno
  67.     addiu $v1, $zero, $a1
  68.     addiu $t1, $zero, $zero   # Contador de caracteres iguales consecutivos
  69. procesar_iguales:
  70.     lw $t0, 0($a1)  # Cargamos el siguiente carácter a comparar
  71.     bne $a0, $t0, procesar_noiguales  # Si no son iguales, terminamos
  72.     addiu $a1, $a1, 1 # Apuntamos al siguiente carácter    
  73.     beq $zero, $zero, procesar_iguales
  74.     addiu $t1, $t1, 1  # Si son iguales, aumentamos el contador en uno
  75.  
  76. procesar_noiguales:
  77.     add $v0, $v0, $t1   # Ponemos los valores de retorno
  78.     add $v1, $v1, $t1
  79. # Volvemos de la función
  80.     jr $ra
  81.     nop
  82.  
Esto empieza a ponerse más interesante, no?  :D Pruébalo a ver si funciona bien. Te aconsejo que pruebes paso a paso, así vas viendo lo que hacen las instrucciones, y ves los valores que hay en los registros, etc...

Otra cuestión: eso que has puesto de jal sig_caract dentro de procesar :huh: te va a montar follones como una casa. La función debe terminar con jr siempre.
Título: Re: RLE en ensamblador MIPS
Publicado por: manurodri189 en Jueves 4 de Junio de 2009, 09:57
Creo que lo he entendido todo excepto esto:

Código: ASM
  1. jr $ra
  2.  

Esto se supone que devuelve el flujo de control a la funcion que lo llamo anteriormente, no? osea a sig_caract, no?

Y otra cosa a la hora de almacenar las salidas lo deberia hacer en procesar_noiguales, no?

Por cierto no te preocupes por los nombres, luego tengo que traducirlo todo al ingles xDDD.

Muchas gracias de nuevo tio.

Salu2

PD: no serás de las pedroñeras, no?
Título: Re: RLE en ensamblador MIPS
Publicado por: manurodri189 en Jueves 4 de Junio de 2009, 10:07
Bueno me he dispuesto a probarlo, y me salta el siguiente error al cargar el archivo:

(http://img142.imageshack.us/img142/479/capturah.png)

Esto que significa?

Salu2
Título: Re: RLE en ensamblador MIPS
Publicado por: m0skit0 en Jueves 4 de Junio de 2009, 10:29
JR sólo copia el registro indicado al registro PC. En este caso $ra. Cuando haces jal, la dirección de ejecución + 8 se guarda en el registro $ra, que sería la dirección de retorno. Es donde volvemos al hacer jr $ra.

Cita de: "manurodri189"
Y otra cosa a la hora de almacenar las salidas lo deberia hacer en procesar_noiguales, no?
Yo no lo haría así. Haría otra función y la llamaría tras procesar(). Ya tienes el número de caracteres y el carácter, sólo habría que almacenar en la dirección de memoria correcta  ;)

Cita de: "manurodri189"
Bueno me he dispuesto a probarlo, y me salta el siguiente error al cargar el archivo:
El PcSpim no es un programa ejemplar que digamos  :lol: Quítale los espacios tras las comas.
Título: Re: RLE en ensamblador MIPS
Publicado por: manurodri189 en Jueves 4 de Junio de 2009, 10:44
Cita de: "m0skit0"
JR sólo copia el registro indicado al registro PC. En este caso $ra. Cuando haces jal, la dirección de ejecución + 8 se guarda en el registro $ra, que sería la dirección de retorno. Es donde volvemos al hacer jr $ra.

Ok, entendido.

Citar
Yo no lo haría así. Haría otra función y la llamaría tras procesar(). Ya tienes el número de caracteres y el carácter, sólo habría que almacenar en la dirección de memoria correcta  ;)

Ok vere a ver si soy capaz de hacer eso.

Citar
El PcSpim no es un programa ejemplar que digamos  :lol: Quítale los espacios tras las comas.

Me he asegurado de quitar todos los espacios tras las comas, y nada, sigue dando exactamente el mismo error. Pero habia mucho mas espacios, porque el error justamente ahi?

Salu2
Título: Re: RLE en ensamblador MIPS
Publicado por: m0skit0 en Jueves 4 de Junio de 2009, 10:54
Cita de: "manurodri189"
Me he asegurado de quitar todos los espacios tras las comas, y nada, sigue dando exactamente el mismo error
Cierto, mein fault! Es add y no addiu
Título: Re: RLE en ensamblador MIPS
Publicado por: manurodri189 en Jueves 4 de Junio de 2009, 12:38
Ok, he cambiado esto:

Código: ASM
  1. procesar:
  2.      addiu $v0, $zero, $zero   # Inicializamos valores de retorno
  3.      addiu $v1, $zero, $a1
  4.      addiu $t1, $zero, $zero   # Contador de caracteres iguales consecutivos
  5.  

por esto:

Código: ASM
  1. procesar:
  2.      add $v0, $zero, $zero   # Inicializamos valores de retorno
  3.      add $v1, $zero, $a1
  4.      add $t1, $zero, $zero   # Contador de caracteres iguales consecutivos
  5.  

Ya que en los 3 me daba el mismo error.

Ahora ejecuto el programa con la cadena "aabb" y se vuelve loco.

(http://img195.imageshack.us/img195/1130/capturaj.png)

Salu2
Título: Re: RLE en ensamblador MIPS
Publicado por: m0skit0 en Jueves 4 de Junio de 2009, 12:55
Error mío otra vez... Si es que... Hay que usar lb y no lw puesto que trabajamos con bytes (caracteres). Perdona. Además hay más cambios, se ve que estaba empanao...

Código: Text
  1. .data
  2. Entrance: .space 80
  3. encode1: .space 40
  4. encode2: .space 40
  5. decode: .space 80
  6. msg1: .asciiz "Please insert the String: "
  7. msg2: .asciiz " "
  8. msg3: .asciiz "n String encode like: "
  9. msg4: .asciiz "n String decode like: "
  10. .text
  11. .globl main
  12.  
  13. #
  14. # Main
  15. #
  16. main:
  17.     ori $v0,$zero,4
  18.     la $a0,msg1
  19.     syscall
  20.  
  21. #Almacenar el String en la matriz
  22. # Número de syscall
  23.     ori $v0,$zero,8
  24. # $a0 = buffer para guardar la cadena
  25.     la $a0,Entrance
  26. # $a1 = tamaño a leer
  27.     ori $a1,$zero,80
  28.     syscall
  29.  
  30. #Imprimir la matriz
  31. # Número de syscall
  32.     ori $v0,$zero,4
  33. # $a0 = buffer a imprimir
  34.     la $a0,Entrance
  35.     syscall
  36.  
  37. #
  38. # Codificar
  39. #
  40. start:
  41.     la $s0, Entrance  
  42. sig_carac:
  43.     lbu $t0, 0($s0)
  44.     beq $t0, $zero, fin   # Si es el carácter de final de cadena, ya terminamos
  45.     add $a0,$zero,$t0     # Pasando el primer parámetro a la función procesar()
  46.     jal procesar          # Si no, llamamos a la función procesar()
  47.     addiu $a1,$s0,1       # Pasando el segundo parámetro a la función procesar()
  48.     beq $zero,$zero,sig_carac  # Siguiente carácter diferente
  49.     ori $s0, $zero, $v1        # Actualizamos el puntero con el valor devuelto
  50.  
  51. #
  52. # Exit
  53. #
  54. fin:
  55.     ori $v0,$zero,10   # Terminamos con exit
  56.     syscall
  57.  
  58. #
  59. # Procesar (habría que poner un nombre más explicativo :)
  60. #
  61. # Recibe un carácter y el puntero a una cadena
  62. # Cuenta cuántos caracteres iguales al pasado consecutivos hay en la cadena
  63. # Devuelve en $v0 el número de caracteres iguales
  64. # y en $v1 el puntero al primer carácter diferente encontrado
  65. procesar:
  66.     addiu $v0, $zero, $zero   # Inicializamos valores de retorno
  67.     addiu $v1, $zero, $a1
  68.     addiu $t1, $zero, $zero   # Contador de caracteres iguales consecutivos
  69. procesar_iguales:
  70.     lbu $t0, 0($a1)              # Cargamos el siguiente carácter a comparar
  71.     bne $a0, $t0, procesar_noiguales  # Si no son iguales, terminamos
  72.     addiu $a1, $a1, 1           # Apuntamos al siguiente carácter    
  73.     beq $zero, $zero, procesar_iguales
  74.     addiu $t1, $t1, 1             # Si son iguales, aumentamos el contador en uno
  75.  
  76. procesar_noiguales:
  77.     add $v0, $v0, $t1   # Ponemos los valores de retorno
  78.     add $v1, $v1, $t1
  79. # Volvemos de la función
  80.     jr $ra
  81.     nop
  82.  
Título: Re: RLE en ensamblador MIPS
Publicado por: manurodri189 en Jueves 4 de Junio de 2009, 13:00
Perdona? no hombre, te estoy muy agradecido, no me pidas perdón encima coño  :lol:

Ahora me tengo que ir luego le hecho un ojo y me pongo con la función esa a ver que sale.

Salu2
Título: Re: RLE en ensamblador MIPS
Publicado por: manurodri189 en Jueves 4 de Junio de 2009, 18:02
Me da este error:

(http://img222.imageshack.us/img222/2084/captura.png)

Supongo que habrá que usar or en vez de ori, no? ya que ori es para un valor inmediato y estamos usando registros, no es asi?

Y si lo cambio, al ejecutar sale esto:

(http://img413.imageshack.us/img413/1130/capturaj.png)

Salu2
Título: Re: RLE en ensamblador MIPS
Publicado por: m0skit0 en Jueves 4 de Junio de 2009, 18:15
Cita de: "manurodri189"
Supongo que habrá que usar or en vez de ori, no? ya que ori es para un valor inmediato y estamos usando registros, no es asi?
Cierto  <_<

¿Lo has ejecutado paso a paso? Mira a ver cuándo te da ese error. A ver si lo pruebo esta tarde...
Título: Re: RLE en ensamblador MIPS
Publicado por: manurodri189 en Jueves 4 de Junio de 2009, 18:26
Ehhhh, estoy aprendiendo verdad? xDDDDD

Lo acabo de ejecutar paso a paso, y me salta justo aqui:

(http://img199.imageshack.us/img199/8572/capturaf.png)

Salu2
Título: Re: RLE en ensamblador MIPS
Publicado por: m0skit0 en Jueves 4 de Junio de 2009, 18:35
Pues tío, yo lo he ejecutado en MARS y no me salta nada de eso, de hecho funciona como debería. Y el error que me pones es del manejador de excepciones del PCSPIM  <_<

Vuelvo a poner el código por si he cambiado algo  :P

Código: Text
  1. .data
  2. Entrance: .space 80
  3. encode1: .space 40
  4. encode2: .space 40
  5. decode: .space 80
  6. msg1: .asciiz "Please insert the String: "
  7. msg2: .asciiz " "
  8. msg3: .asciiz "n String encode like: "
  9. msg4: .asciiz "n String decode like: "
  10. .text
  11. .globl main
  12.  
  13. #
  14. # Main
  15. #
  16. main:
  17.     ori $v0,$zero,4
  18.     la $a0,msg1
  19.     syscall
  20.  
  21. #Almacenar el String en la matriz
  22. # Número de syscall
  23.     ori $v0,$zero,8
  24. # $a0 = buffer para guardar la cadena
  25.     la $a0,Entrance
  26. # $a1 = tamaño a leer
  27.     ori $a1,$zero,80
  28.     syscall
  29.  
  30. #Imprimir la matriz
  31. # Número de syscall
  32.     ori $v0,$zero,4
  33. # $a0 = buffer a imprimir
  34.     la $a0,Entrance
  35.     syscall
  36.  
  37. #
  38. # Codificar
  39. #
  40. start:
  41.     la $s0, Entrance  
  42. sig_carac:
  43.     lbu $t0, 0($s0)
  44.     beq $t0, $zero, fin   # Si es el carácter de final de cadena, ya terminamos
  45.     add $a0,$zero,$t0     # Pasando el primer parámetro a la función procesar()
  46.     jal procesar          # Si no, llamamos a la función procesar()
  47.     addiu $a1,$s0,1       # Pasando el segundo parámetro a la función procesar()
  48.     beq $zero,$zero,sig_carac  # Siguiente carácter diferente
  49.     or $s0, $zero, $v1        # Actualizamos el puntero con el valor devuelto
  50.  
  51. #
  52. # Exit
  53. #
  54. fin:
  55.     ori $v0,$zero,10   # Terminamos con exit
  56.     syscall
  57.  
  58. #
  59. # Procesar (habría que poner un nombre más explicativo :)
  60. #
  61. # Recibe un carácter y el puntero a una cadena
  62. # Cuenta cuántos caracteres iguales al pasado consecutivos hay en la cadena
  63. # Devuelve en $v0 el número de caracteres iguales
  64. # y en $v1 el puntero al primer carácter diferente encontrado
  65. procesar:
  66.     add $v0, $zero, $zero   # Inicializamos valores de retorno
  67.     add $v1, $zero, $a1
  68.     add $t1, $zero, $zero   # Contador de caracteres iguales consecutivos
  69. procesar_iguales:
  70.     lbu $t0, 0($a1)                    # Cargamos el siguiente carácter a comparar
  71.     bne $a0, $t0, procesar_noiguales   # Si no son iguales, terminamos
  72.     addiu $a1, $a1, 1                  # Apuntamos al siguiente carácter    
  73.     beq $zero, $zero, procesar_iguales
  74.     addiu $t1, $t1, 1                  # Si son iguales, aumentamos el contador en uno
  75.  
  76. procesar_noiguales:
  77.     add $v0, $v0, $t1   # Ponemos los valores de retorno
  78.     add $v1, $v1, $t1
  79. # Volvemos de la función
  80.     jr $ra
  81.     nop
  82.  
Y si quieres prueba el MARS, que personalmente prefiero al PCSPIM, porque tiene una interfaz más intuitiva y más legible, se puede volcar la memoria, etc... : http://courses.missouristate.edu/KenVol ... wnload.htm (http://courses.missouristate.edu/KenVollmar/MARS/download.htm" onclick="window.open(this.href);return false;)

Eso sí, es un JAR (fistro! xD) y necesitarás una máquina virtual Java para que tire.
Título: Re: RLE en ensamblador MIPS
Publicado por: manurodri189 en Jueves 4 de Junio de 2009, 18:43
En el PCSPIM, me da el mismo error.

Me he bajado el MARS y la verdad es que tiene mejor pinta, pero en la salida me pone esto:

Citar
Assemble: assembling C:Documents and SettingsAdministradorEscritorioencode2.asm

Assemble: operation completed successfully.

Go: running encode2.asm

Error in encode2.asm line 70: Runtime exception at 0x0040006c: address out of range 0x00000050

Go: execution terminated with errors.

Creo que seguiré usando el PCSPIM, más que nada, porque el que me lo mandó usa PCSPIM, y lo va a probar en ese.

Salu2
Título: Re: RLE en ensamblador MIPS
Publicado por: m0skit0 en Jueves 4 de Junio de 2009, 19:10
Yo no sé qué pasa, si no copias bien el código, o cómo... Mira, he puesto que imprima el resultado, te vuelvo a postear el código y una captura del programa corriendo en el MARS. Si te sigue dando ese error en el PCSPIM coméntaselo a tu profe/jefe/loquesea.

Código: Text
  1. .data
  2. Entrance: .space 80
  3. encode1: .space 40
  4. encode2: .space 40
  5. decode: .space 80
  6. msg1: .asciiz "Please insert the String: "
  7. msg2: .asciiz " "
  8. msg3: .asciiz "n String encode like: "
  9. msg4: .asciiz "n String decode like: "
  10. .text
  11. .globl main
  12.  
  13. #
  14. # Main
  15. #
  16. main:
  17.     ori $v0,$zero,4
  18.     la $a0,msg1
  19.     syscall
  20.  
  21. #Almacenar el String en la matriz
  22. # Número de syscall
  23.     ori $v0,$zero,8
  24. # $a0 = buffer para guardar la cadena
  25.     la $a0,Entrance
  26. # $a1 = tamaño a leer
  27.     ori $a1,$zero,80
  28.     syscall
  29.  
  30. #Imprimir la matriz
  31. # Número de syscall
  32.     ori $v0,$zero,4
  33. # $a0 = buffer a imprimir
  34.     la $a0,Entrance
  35.     syscall
  36.  
  37. #
  38. # Codificar
  39. #
  40. start:
  41.     la $s0, Entrance  
  42. sig_carac:
  43.     lbu $t0, 0($s0)
  44.     beq $t0, $zero, fin   # Si es el carácter de final de cadena, ya terminamos
  45.     add $a0,$zero,$t0     # Pasando el primer parámetro a la función procesar()
  46.    
  47.     jal procesar          # Llamamos a la función procesar()
  48.     addiu $a1,$s0,1       # Pasando el segundo parámetro a la función procesar()
  49.    
  50.     addiu $a0,$v0,1
  51.     addiu $v0,$zero,1
  52.     syscall
  53.    
  54.     beq $zero,$zero,sig_carac  # Siguiente carácter diferente
  55.     or $s0, $zero, $v1        # Actualizamos el puntero con el valor devuelto
  56.  
  57. #
  58. # Exit
  59. #
  60. fin:
  61.     ori $v0,$zero,10   # Terminamos con exit
  62.     syscall
  63.  
  64. #
  65. # Procesar (habría que poner un nombre más explicativo :)
  66. #
  67. # Recibe un carácter y el puntero a una cadena
  68. # Cuenta cuántos caracteres iguales al pasado consecutivos hay en la cadena
  69. # Devuelve en $v0 el número de caracteres iguales
  70. # y en $v1 el puntero al primer carácter diferente encontrado
  71. procesar:
  72.     add $v0, $zero, $zero   # Inicializamos valores de retorno
  73.     add $v1, $zero, $a1
  74.     add $t1, $zero, $zero   # Contador de caracteres iguales consecutivos
  75. procesar_iguales:
  76.     lbu $t0, 0($a1)                    # Cargamos el siguiente carácter a comparar
  77.     bne $a0, $t0, procesar_noiguales   # Si no son iguales, terminamos
  78.     addiu $a1, $a1, 1                  # Apuntamos al siguiente carácter    
  79.     beq $zero, $zero, procesar_iguales
  80.     addiu $t1, $t1, 1                  # Si son iguales, aumentamos el contador en uno
  81.  
  82. procesar_noiguales:
  83.     add $v0, $v0, $t1   # Ponemos los valores de retorno
  84.     add $v1, $v1, $t1
  85. # Volvemos de la función
  86.     jr $ra
  87.     nop
  88.  
Y la captura:
[attachment=0:2y3tse4c]captura1.jpg[/attachment:2y3tse4c]
El uno que sale al final es por el ENTER, sólo es cuestión de suprimirlo o sustituír la comparación con ASCII cero por ASCII 10.

Ya me comentas, un saludo

PD: no puedo usar el PCSPIM en el curro porque necesita de instalación y no tengo permisos para ello
Título: Re: RLE en ensamblador MIPS
Publicado por: manurodri189 en Jueves 4 de Junio de 2009, 19:32
Debe de ser problema mio, pero no entiendo porque, yo solamente copio el texto a un block de notas y le cambio la extensin de txt a asm.

Si lo ejecuto en PCSPIM, me da esa exception y me imprime infinitos "1" y tengo que cerrar el programa, y si lo ejecuto en MARS, me da esto:

Citar
Assemble: assembling C:Documents and SettingsRaistlinEscritorioencode.asm

Assemble: operation completed successfully.

Go: running encode.asm

Error in encode.asm line 76: Runtime exception at 0x00400078: address out of range 0x00000050

Go: execution terminated with errors.

He probado con 2 ordenadores diferentes, no puedo imaginar cual es el problema.

Salu2

PD: es profesor.
Título: Re: RLE en ensamblador MIPS
Publicado por: m0skit0 en Jueves 4 de Junio de 2009, 20:50
Bueno, he averiguado lo que pasa. Esto pasa porque no haces caso a lo que digo  :P  :D No tienes activado el "delayed branching". Esto deberías dejarlo siempre puesto porque en la realidad los procesadores MIPS funcionan así.

Venga, a currar  :comp:  ;)
Título: Re: RLE en ensamblador MIPS
Publicado por: manurodri189 en Viernes 5 de Junio de 2009, 10:25
Dios!!! era eso!!!. Si te escucho tio :rolleyes:  pero eso se me pasó.

Ahora a ver si lo he entendido, tengo que hacer una funcion nueva para que me almacene el contador en encode2 y el caracter en encode1, me dices que la llamarias detras de procesar, pero no se si te refieres a llamarla inmediatamente detrás de procesar o de todo el proceso, osea procesar_noiguales, yo es que solo concibo llamarla despues de procesar_noiguales.

Entiendo que el contador esta almacenado en el registro t1, osea el contenido de t1 es el numero de repeticiones de un caracter. Y el caracter esta referido desde el puntero, osea que supongo que accediendo a 0($a0) tengo el caracter no es asi?

Ahora bien, seria tan facil como hacer:

Código: ASM
  1. add $t3,$zero,encode1 #almaceno el puntero encode1 en t3
  2. add $t4,$zero,encode2 #almaceno el puntero encode2 en t4
  3.  
  4. add $t4(0),$zero,$t1 #en la primera direccion almacendo el contador.
  5. add $t3(0),$zero,0($a0) #en la primera direccion almacendo el caracter.
  6.  
  7. #Avanzo los punteros a la siguiente posicion
  8.  
  9. addiu $t3,$zero,1
  10. addiu $t4,$zero,1
  11.  

Que te parece?

Salu2
Título: Re: RLE en ensamblador MIPS
Publicado por: m0skit0 en Viernes 5 de Junio de 2009, 10:49
Cita de: "manurodri189"
seria tan facil como hacer:
Me parece que ese código no te va a funcionar porque es erróneo, y mucho. Pruébalo y verás lo que te dice el simulador. Te falta por aprender ensamblador MIPS básico... y te aconsejo que te pongas las pilas, porque no siempre vas a tener el foro delante, no sé si me explico  :P

Cita de: "manurodri189"
me dices que la llamarias detras de procesar, pero no se si te refieres a llamarla inmediatamente detrás de procesar o de todo el proceso, osea procesar_noiguales, yo es que solo concibo llamarla despues de procesar_noiguales.
Puedes hacerlo como te dé la gana, siempre que funcione, aunque al final voy a terminar haciéndolo todo yo  :lol: Yo lo que digo es hacer otra función que se llame tras procesar(), por ejemplo llamada almacenar():

Código: Text
  1. #
  2. # Codificar
  3. #
  4. start:
  5.     la $s0, Entrance  
  6. sig_carac:
  7.     lbu $s1, 0($s0)
  8.     beq $s1, $zero, fin   # Si es el carácter de final de cadena, ya terminamos
  9.     add $a0,$zero,$s1     # Pasando el primer parámetro a la función procesar()
  10.    
  11.     jal procesar          # Llamamos a la función procesar()
  12.     addiu $a1,$s0,1       # Pasando el segundo parámetro a la función procesar()
  13.    
  14.     add $a0,$zero,$s1  #El carácter en $a0
  15.     jal almacenar     # Llamamos a la función almacenar()
  16.     add $a1,$zero,$v0  # Ponemos el número de caracteres en $a1
  17.  
  18.     beq $zero,$zero,sig_carac  # Siguiente carácter diferente
  19.     or $s0, $zero, $v1        # Actualizamos el puntero con el valor devuelto
  20.  
  21. #
  22. # Exit
  23. #
  24. fin:
  25.     ori $v0,$zero,10   # Terminamos con exit
  26.     syscall
  27.  
Fíjate que he cambiado $t0 por $s1, así mantenemos el carácter en un registro y se lo podemos pasar a almacenar(), ya que procesar() modifica $t0. Por convenio, en MIPS los registros sX deben mantener el valor a la vuelta de la función, mientras que los tX no tienen por qué.

Sólo quedaría por hacer la función almacenar(), claro. Pero si quieres meterlo todo en la misma función, tú mismo. A mí simplemente me parecen dos funciones diferentes, y así incluso podrías usar procesar() o almacenar() para otro ejercicio u proyecto.

Bueno, ya me dices, un saludo :hola: y mírate las instrucciones de MIPS bien  <_<
Título: Re: RLE en ensamblador MIPS
Publicado por: manurodri189 en Viernes 5 de Junio de 2009, 11:37
Citar
Me parece que ese código no te va a funcionar porque es erróneo, y mucho. Pruébalo y verás lo que te dice el simulador. Te falta por aprender ensamblador MIPS básico... y te aconsejo que te pongas las pilas, porque no siempre vas a tener el foro delante, no sé si me explico  :P

Creo que estoy pillando cosillas, pero la verdad es que estoy verde verde, y como tu bien dices, no voy a tenerte aqui siempre, eso es cierto.

Citar
Puedes hacerlo como te dé la gana, siempre que funcione, aunque al final voy a terminar haciéndolo todo yo  :lol: Yo lo que digo es hacer otra función que se llame tras procesar(), por ejemplo llamada almacenar()

Sólo quedaría por hacer la función almacenar(), claro. Pero si quieres meterlo todo en la misma función, tú mismo. A mí simplemente me parecen dos funciones diferentes, y así incluso podrías usar procesar() o almacenar() para otro ejercicio u proyecto.

Vale vale, ya lo pillo, pense que te referias a otra cosa.

Citar
Bueno, ya me dices, un saludo :hola: y mírate las instrucciones de MIPS bien  <_<

El documento que uso para mirar el repertorio de instrucciones es este:

http://rapidshare.com/files/235243032/R ... S.pdf.html (http://rapidshare.com/files/235243032/Repertorio_instrucciones_MIPS.pdf.html" onclick="window.open(this.href);return false;)

Creo que esta bien explicado, pero hay cosas que no me quedan claras, y por eso dudo, por ejemplo, ya me he dado cuenta que para cargar la direccion hay que usar la, pero para cargar el dato directamente en una direccion de memoria no se exactamente la funcion que tengo que usar, si sw, sb u otra, pongo esto:

Código: ASM
  1. almacenar:
  2.     la $s3, encode1  #almaceno la direccion de encode1 en s3, s3 es el puntero
  3.     la $s4, encode2  #almaceno la direccion de encode2 en s4, s4 es el puntero
  4.  
  5.     sw $t1,$s3   #meto el caracter en la primera direccion de s3
  6.     sw $s1,$s3   #meto el contador en la primera direccion de s4
  7.  
  8.     #avanzo el puntero
  9.  
  10.     addiu $s3,$zero,1
  11.     addiu $s3,$zero,1
  12.  

o esto:

Código: ASM
  1. almacenar:
  2.     la $s3, encode1  #almaceno la direccion de encode1 en s3, s3 es el puntero
  3.     la $s4, encode2  #almaceno la direccion de encode2 en s4, s4 es el puntero
  4.  
  5.     sb $t1,$s3   #meto el caracter en la primera direccion de s3
  6.     sb $s1,$s3   #meto el contador en la primera direccion de s4
  7.  
  8.     #avanzo el puntero
  9.  
  10.     addiu $s3,$zero,1
  11.     addiu $s3,$zero,1
  12.  

Y me casca, en el sb o sw, pero es que no encuentro otra instruccion de store que me pueda hacer eso.

Salu2
Título: Re: RLE en ensamblador MIPS
Publicado por: m0skit0 en Viernes 5 de Junio de 2009, 11:50
La diferencia entre sb y sw es muy simple: ambos guardan un registro en la memoria, pero sb guarda tan sólo el byte bajo mientras que sw guarda el registro entero (una palabra, 4 bytes). Así que evidentemente tenemos que usar sb para los caracteres (un carácter = un byte) y sw para los números (sólo para tener una rango más grande, se podría usar sb perfectamente). Tu problema radica en que tienes mal la sintaxis de sb (o sw, lb, lw, es la misma):

Código: Text
  1. sb registro, desplazamiento(registro_puntero)
  2.  
Y siempre es así, aunque el desplazamiento sea cero, hay que poner un cero.

Además, acuérdate de que las funciones no deberían modificar el valor de los registros sX, o si lo hacen deben restaurar el valor que tenían previamente.

Ánimo, que ya casi lo tienes  ^_^
Título: Re: RLE en ensamblador MIPS
Publicado por: manurodri189 en Viernes 5 de Junio de 2009, 12:06
Bien, creo que lo he entendido, ahora no me da fallo al ejecutarlo, pongo el método:

Código: ASM
  1. almacenar:
  2.     la $s3, encode1  #almaceno la direccion de encode1 en s3, s3 es el puntero
  3.     la $s4, encode2  #almaceno la direccion de encode2 en s4, s4 es el puntero
  4.  
  5.     #sb para caracter
  6.     #sw para los numeros
  7.     sb $t1,0($s3)   #meto el caracter en la primera direccion de s3
  8.     sw $s1,0($s3)   #meto el contador en la primera direccion de s4
  9.  
  10.     #avanzo el puntero
  11.  
  12.     addiu $s3,$zero,1
  13.     addiu $s3,$zero,1
  14.  
  15. # Volvemos de la función
  16.     jr $ra
  17.     nop
  18.  

Bien, no te entendi bien esto:

Citar
Además, acuérdate de que las funciones no deberían modificar el valor de los registros sX, o si lo hacen deben restaurar el valor que tenían previamente.

Osea en los Sx, debo almacenar algo, y dejarlo perenne? entonces seria mejor que usara los registros tX en la funcion almacenar en vez de los sX, no?

Ahora intento imprimirlo para ver si lo he hecho bien:

Código: ASM
  1. fin:
  2.  
  3.     ori $v0,$zero,4
  4.     la $a0,encode1
  5.     syscall
  6.  
  7.     ori $v0,$zero,4
  8.     la $a0,encode2
  9.     syscall
  10.  
  11.     ori $v0,$zero,10   # Terminamos con exit
  12.     syscall
  13.  

Pero el programa no imprime nada, osea que algo en almacenar no tira, porque creo que lo de imprimir si lo cogí.

Salu2
Título: Re: RLE en ensamblador MIPS
Publicado por: m0skit0 en Viernes 5 de Junio de 2009, 12:26
Código: Text
  1. sb $t1,0($s3)   #meto el caracter en la primera direccion de s3
  2. sw $s1,0($s3)
  3.  
¿Esto qué es, tíooooooo? Primero, los argumentos de la función se pasan en a0 y a1, no sé qué haces almacenando t1 y s1  :huh: Además, estás usando s3 como puntero de desetino en ambos, ¿entonces para qué cargas s4?  <_<

Cita de: "manurodri189"
entonces seria mejor que usara los registros tX en la funcion almacenar en vez de los sX, no?
Sí, eso exactamente.

Cita de: "manurodri189"
Ahora intento imprimirlo para ver si lo he hecho bien:
Para ver si lo has hecho bien, depura paso a paso.
Título: Re: RLE en ensamblador MIPS
Publicado por: manurodri189 en Viernes 5 de Junio de 2009, 12:45
Lo de s3 es que se me ha pasado, en el segundo queria poner s4.

Vale lo de a0 lo entiendo, es ciero que se pasaban por esos registros, aunque el caracter este también en s1.

Pero lo de a1, no, en a1 esta el siguiente caracter y no el contador, que, no? osea si es asi, entonces en no_iguales tendria que guardar el $t1 en un registro aX como puede ser el a4, no?

Salu2
Título: Re: RLE en ensamblador MIPS
Publicado por: m0skit0 en Viernes 5 de Junio de 2009, 12:50
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.  
En a0 el carácter, en a1 el número de caracteres. A ver si leemos  :P

Cita de: "manurodri189"
Vale lo de a0 lo entiendo, es ciero que se pasaban por esos registros, aunque el caracter este también en s1.
Sí, pero te tienes que atener a los parámetros de la función. Si usas la función en otro programa por ejemplo, $s1 no tiene por qué tener ese carácter. Piensa en la función como un programa aparte  ;)
Título: Re: RLE en ensamblador MIPS
Publicado por: manurodri189 en Viernes 5 de Junio de 2009, 13:05
:ouch: vaya paciencia la tuya  :D

Salu2
Título: Re: RLE en ensamblador MIPS
Publicado por: manurodri189 en Viernes 5 de Junio de 2009, 13:11
Ahora me pasa una cosa rarisima.

Dejo la funcion así:

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

y para finalizar el programa e imprimir asi:

Código: ASM
  1. fin:
  2.  
  3.     ori $v0,$zero,4
  4.     la $a0,encode1
  5.     syscall
  6.  
  7.     ori $v0,$zero,4
  8.     la $a0,encode2
  9.     syscall
  10.  
  11.     ori $v0,$zero,10   # Terminamos con exit
  12.     syscall
  13.  

Pues bien cuando lo ejecuto todo de golpe, no hace nada, se queda seco.

Y cuando lo ejecuto paso por paso, cuando acaba empieza a dar excepciones del tipo:

(http://img195.imageshack.us/img195/4636/capturan.png)

Se supone que lo tengo guardado en encode1 y encode2, no?

Salu2
Título: Re: RLE en ensamblador MIPS
Publicado por: m0skit0 en Viernes 5 de Junio de 2009, 13:28
Sigues cometiendo varios errores, incluído el del syscall  <_<

Empecemos por la función:

Código: Text
  1.  #avanzo el puntero
  2.  
  3.     addiu $t3,$zero,1
  4.     addiu $t4,$zero,1
  5.  
¿Avanzas el puntero? Yo sólo veo que asignas t3 = 1  y t4 = 1. Eso no es avanzar el puntero. Además, el avance de los punteros tendrías devolver los punteros actualizados al programa principal, para no sobreescribir siempre el mismo valor. Y evidentemente actualizarlos en el programa principal.

Código: Text
  1. ori $v0,$zero,4
  2. la $a0,encode2
  3. syscall
  4.  
La función 4 de syscall imprime una cadena de caracteres, no un array de números  <_<
Título: Re: RLE en ensamblador MIPS
Publicado por: manurodri189 en Viernes 5 de Junio de 2009, 14:01
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
Título: Re: RLE en ensamblador MIPS
Publicado por: m0skit0 en Viernes 5 de Junio de 2009, 14:21
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
Título: Re: RLE en ensamblador MIPS
Publicado por: manurodri189 en Viernes 5 de Junio de 2009, 14:46
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
Título: Re: RLE en ensamblador MIPS
Publicado por: m0skit0 en Viernes 5 de Junio de 2009, 17:35
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.
Título: Re: RLE en ensamblador MIPS
Publicado por: manurodri189 en Sábado 6 de Junio de 2009, 12:43
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
Título: Re: RLE en ensamblador MIPS
Publicado por: m0skit0 en Sábado 6 de Junio de 2009, 13:10
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.
Título: Re: RLE en ensamblador MIPS
Publicado por: manurodri189 en Sábado 6 de Junio de 2009, 13:16
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
Título: Re: RLE en ensamblador MIPS
Publicado por: m0skit0 en Sábado 6 de Junio de 2009, 14:41
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.
Título: Re: RLE en ensamblador MIPS
Publicado por: manurodri189 en Viernes 12 de Junio de 2009, 09:28
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.
Título: Re: RLE en ensamblador MIPS
Publicado por: manurodri189 en Viernes 12 de Junio de 2009, 09:41
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.  
Título: Re: RLE en ensamblador MIPS
Publicado por: manurodri189 en Viernes 12 de Junio de 2009, 11:09
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:
Título: Re: RLE en ensamblador MIPS
Publicado por: m0skit0 en Viernes 12 de Junio de 2009, 13:24
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 ;)
Título: Re: RLE en ensamblador MIPS
Publicado por: manurodri189 en Viernes 12 de Junio de 2009, 13:44
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
Título: Re: RLE en ensamblador MIPS
Publicado por: m0skit0 en Viernes 12 de Junio de 2009, 13:58
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.
Título: Re: RLE en ensamblador MIPS
Publicado por: manurodri189 en Viernes 12 de Junio de 2009, 14:01
Ok, entiendo se me pasó poner nop detras de la instruccion, con uno seria suficiente, no?

Salu2

PD: sigue sin tirar.
Título: Re: RLE en ensamblador MIPS
Publicado por: m0skit0 en Viernes 12 de Junio de 2009, 14:10
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.
Título: Re: RLE en ensamblador MIPS
Publicado por: manurodri189 en Viernes 12 de Junio de 2009, 14:14
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
Título: Re: RLE en ensamblador MIPS
Publicado por: m0skit0 en Viernes 12 de Junio de 2009, 14:19
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  ;)
Título: Re: RLE en ensamblador MIPS
Publicado por: manurodri189 en Viernes 12 de Junio de 2009, 14:45
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.
Título: Re: RLE en ensamblador MIPS
Publicado por: manurodri189 en Viernes 12 de Junio de 2009, 14:56
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
Título: Re: RLE en ensamblador MIPS
Publicado por: m0skit0 en Viernes 12 de Junio de 2009, 15:00
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.
Título: Re: RLE en ensamblador MIPS
Publicado por: manurodri189 en Viernes 12 de Junio de 2009, 15:09
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
Título: Re: RLE en ensamblador MIPS
Publicado por: m0skit0 en Viernes 12 de Junio de 2009, 17:16
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.  
Título: Re: RLE en ensamblador MIPS
Publicado por: manurodri189 en Viernes 12 de Junio de 2009, 20:14
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
Título: Re: RLE en ensamblador MIPS
Publicado por: m0skit0 en Sábado 13 de Junio de 2009, 15:30
: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:
Título: Re: RLE en ensamblador MIPS
Publicado por: manurodri189 en Sábado 13 de Junio de 2009, 18:12
Tienes toda la razon, tio.

De hecho ya he acabado el programa, y se que funciona, gracias a la ejecucion paso a paso, y a lo que me pone en los registros.

El almacenar_salida, como preveia estaba mal y como se supone que entendí el código que me pasaste de decodificar, pues he visto que cometia los mismos errores que comentabas antes, lo de leer en vez de escribir y demas.

Aqui pongo el codigo que me ha quedado de almacenar_salida, pero ya te digo que funciona, porque lo he probado.

Código: ASM
  1. almacenar_salida:
  2.     la $a0,encode1
  3.     la $a1,encode2
  4.     la $a3,encode
  5.     or $t0,$zero,$a0   # encode1
  6.     or $t1,$zero,$a1   # encode2
  7.     or $t2,$zero,$a3   # encode
  8.  
  9.  
  10. while:
  11.  
  12.     lbu $t3,0($t0)  # Carácter de "encode1" -> T3    
  13.     addiu $t0,$t0,1  # Avanzamos puntero
  14.     lbu $t4,0($t1)  # Numero de "encode2" -> T4  
  15.  
  16.     beq $t3,$zero,finwhile    #si es el caracter vacio acabo
  17.     nop
  18.     sb $t4,0($t2)              #cargo el primer numero en encode
  19.     addiu $t2,$t2,1             #avanzo el puntero de encode
  20.     sb $t3,0($t2)              #cargo el caracter en encode
  21.  
  22.     #avanzo todos los punteros
  23.     addiu $t1,$t1,1
  24.     addiu $t2,$t2,1
  25.  
  26.     b while                   #llamo a while de nuevo
  27.     nop
  28.  

Ahora solo tengo un pequeño problemilla que no se a que se debe. Y es a la hora de imprimir encode, y solo encode, porque los numeros me los imprime como caracteres extraños, no se si será por el syscall o porque, pero solo me pasa con el encode, ya que si imprimo el decode de la misma manera funciona perfectamente.

Lo imprimo así:

Código: ASM
  1. #Imprimir la matriz de salida codificada
  2.     # Número de syscall
  3.     ori $v0,$zero,4
  4.     # $a0 = buffer a imprimir
  5.     la $a0,encode
  6.     syscall
  7.  

Y da como salida esto:

Citar
Entrance String: aabbcc

 String encode like: abc

 String decode like: aabbcc

Te pego todo el programa acabado a falta de eso:

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 "n"
  9. msg3: .asciiz "n String encode like: "
  10. msg4: .asciiz "n String decode like: "
  11. msg5: .asciiz "n Entrance String: "
  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,Entrance
  28. # $a1 = tamaño a leer
  29.     ori $a1,$zero,80
  30.     syscall
  31.  
  32. la $a0,Entrance
  33. jal eliminar_enter
  34. nop
  35.  
  36. ori $v0,$zero,4
  37.     la $a0,msg5
  38.     syscall
  39.  
  40. #Imprimir la matriz
  41. # Número de syscall
  42.     ori $v0,$zero,4
  43. # $a0 = buffer a imprimir
  44.     la $a0,Entrance
  45.     syscall
  46.  
  47. ori $v0,$zero,4
  48.     la $a0,msg2
  49.     syscall
  50.  
  51. #
  52. # Codificar
  53. #
  54. start:
  55.     la $s0, Entrance
  56.     la $s3, encode1  #almaceno la direccion de encode1 en s3, s3 es el puntero
  57.     la $s4, encode2  #almaceno la direccion de encode2 en s4, s4 es el puntero
  58.     or $a3,$zero,$s3
  59.     or $a2,$zero,$s4
  60.  
  61. sig_carac:
  62.     lbu $s1, 0($s0)
  63.     beq $s1, $zero, fin   # Si es el carácter de final de cadena, ya terminamos
  64.     add $a0,$zero,$s1     # Pasando el primer parámetro a la función procesar()
  65.    
  66.     jal procesar          # Llamamos a la función procesar()
  67.     addiu $a1,$s0,1       # Pasando el segundo parámetro a la función procesar()
  68.    
  69.     add $a0,$zero,$s1  #El carácter en $a0
  70.     addiu $v0,$v0,1    #sumamos 1 a v0
  71.     jal almacenar     # Llamamos a la función almacenar()
  72.     add $a1,$zero,$v0  # Ponemos el número de caracteres en $a1
  73.    
  74.     beq $zero,$zero,sig_carac  # Siguiente carácter diferente
  75.     or $s0, $zero, $v1        # Actualizamos el puntero con el valor devuelto
  76.  
  77. #
  78. # Exit
  79. #
  80. fin:
  81.  
  82.     jal almacenar_salida
  83.     nop
  84.  
  85.     ori $v0,$zero,4
  86.     la $a0,msg3
  87.     syscall
  88.  
  89.     #Imprimir la matriz
  90.     # Número de syscall
  91.     ori $v0,$zero,4
  92.     # $a0 = buffer a imprimir
  93.     la $a0,encode
  94.     syscall
  95.  
  96.     ori $v0,$zero,4
  97.     la $a0,msg2
  98.     syscall
  99.  
  100.     jal decodificar
  101.     nop
  102.  
  103.     ori $v0,$zero,4
  104.     la $a0,msg4
  105.     syscall
  106.  
  107.     #Imprimir la matriz
  108.     # Número de syscall
  109.     ori $v0,$zero,4
  110.     # $a0 = buffer a imprimir
  111.     la $a0,decode
  112.     syscall
  113.  
  114.     ori $v0,$zero,4
  115.     la $a0,msg2
  116.     syscall
  117.  
  118.     ori $v0,$zero,10   # Terminamos con exit
  119.     syscall
  120.  
  121. #
  122. # Procesar (habría que poner un nombre más explicativo :)
  123. #
  124. # Recibe un carácter y el puntero a una cadena
  125. # Cuenta cuántos caracteres iguales al pasado consecutivos hay en la cadena
  126. # Devuelve en $v0 el número de caracteres iguales
  127. # y en $v1 el puntero al primer carácter diferente encontrado
  128. procesar:
  129.     add $v0, $zero, $zero   # Inicializamos valores de retorno
  130.     add $v1, $zero, $a1
  131.     add $t1, $zero, $zero   # Contador de caracteres iguales consecutivos
  132. procesar_iguales:
  133.     lbu $t0, 0($a1)                    # Cargamos el siguiente carácter a comparar
  134.     bne $a0, $t0, procesar_noiguales   # Si no son iguales, terminamos
  135.     addiu $a1, $a1, 1                  # Apuntamos al siguiente carácter    
  136.     beq $zero, $zero, procesar_iguales
  137.     addiu $t1, $t1, 1                  # Si son iguales, aumentamos el contador en uno
  138.  
  139. procesar_noiguales:
  140.     add $v0, $v0, $t1   # Ponemos los valores de retorno
  141.     add $v1, $v1, $t1
  142.  
  143.  
  144. # Volvemos de la función
  145.     jr $ra
  146.     nop
  147.  
  148.  
  149. almacenar:
  150.  
  151.     sb $a0,0($a3)   #meto el caracter en la primera direccion de a3
  152.     sb $a1,0($a2)   #meto el contador en la primera direccion de a4
  153.  
  154.     #avanzo el puntero
  155.  
  156.     addiu $a3,$a3,1
  157.     addiu $a2,$a2,1
  158.  
  159.  
  160.  
  161. # Volvemos de la función
  162.     jr $ra
  163.     nop
  164.  
  165. almacenar_salida:
  166.     la $a0,encode1
  167.     la $a1,encode2
  168.     la $a3,encode
  169.     or $t0,$zero,$a0   # encode1
  170.     or $t1,$zero,$a1   # encode2
  171.     or $t2,$zero,$a3   # encode
  172.  
  173.  
  174. while:
  175.  
  176.     lbu $t3,0($t0)  # Carácter de "encode1" -> T3    
  177.     addiu $t0,$t0,1  # Avanzamos puntero
  178.     lbu $t4,0($t1)  # Numero de "encode2" -> T4  
  179.  
  180.     beq $t3,$zero,finwhile    #si es el caracter vacio acabo
  181.     nop
  182.     sb $t4,0($t2)              #cargo el primer numero en encode
  183.     addiu $t2,$t2,1             #avanzo el puntero de encode
  184.     sb $t3,0($t2)              #cargo el caracter en encode
  185.  
  186.     #avanzo todos los punteros
  187.     addiu $t1,$t1,1
  188.     addiu $t2,$t2,1
  189.  
  190.     b while                   #llamo a while de nuevo
  191.     nop
  192.  
  193. finwhile:
  194.  
  195.     sb $zero, 0($t2)   # Escribimos el carácter de fin de cadena
  196.     jr $ra
  197.     nop
  198.  
  199.  
  200. # void EliminarEnter(char* entrada)
  201. eliminar_enter:
  202.     li $t1,0xA
  203. ee_bucle:
  204.     lbu $t0,0($a0)
  205.     beq $t0,0xA,fin_ee
  206.     addiu $a0,$a0,1
  207.     beq $zero,$zero,ee_bucle
  208.     nop
  209. fin_ee:
  210.     jr $ra
  211.     sb $zero,-1($a0)
  212.  
  213.  
  214. decodificar:
  215.     # cargamos los parámetros en otros registros
  216.     la $a2,decode
  217.     la $a0,encode1
  218.     la $a1,encode2
  219.     or $t0,$zero,$a0   # encode1
  220.     or $t1,$zero,$a1   # encode2
  221.     or $t2,$zero,$a2   # decode
  222.  
  223.     lbu $t3,0($t0)  # Carácter de "encode1" -> T3    
  224.     addiu $t0,$t0,1  # Avanzamos puntero
  225.  
  226. decode_while1:    
  227.     beq $t3,$zero,fin_dec_while1  # Mientras no sea fin de cadena
  228.     nop
  229.     lbu $t4, 0($t1)  # Número de repeticiones del carácter
  230.     addiu $t1,$t1,1  # Avanzamos de elemento
  231.  
  232. decode_while2:
  233.     beq $t4,$zero,fin_dec_while2  # Mientras el número de caracteres no sea cero
  234.     nop
  235.     sb $t3, 0($t2)   # Escribimos el carácter en decode
  236.     addiu $t2,$t2,1  # Avanzamos el puntero móvil de decode
  237.     beq $zero,$zero, decode_while2  # Repetimos
  238.     addiu $t4,$t4,-1  # Restamos uno al número de caracteres
  239.  
  240. fin_dec_while2:    
  241.     lbu $t3,0($t0)  # Carácter de "encode1" -> T3    
  242.     beq $zero,$zero,decode_while1
  243.     addiu $t0,$t0,1  # Avanzamos puntero
  244.  
  245. fin_dec_while1:
  246.     sb $zero, 0($t2)   # Escribimos el carácter de fin de cadena
  247.     jr $ra
  248.     nop
  249.  
  250.  

Saludos y muchas gracias de nuevo.
Título: Re: RLE en ensamblador MIPS
Publicado por: m0skit0 en Sábado 13 de Junio de 2009, 20:11
Cita de: "manurodri189"
Y es a la hora de imprimir encode, y solo encode, porque los numeros me los imprime como caracteres extraños
Esto ya lo comentamos  :lol: Estás usando la llamada al sistema 4, que es para imprimir cadenas de caracteres, no vectores de números.
Título: Re: RLE en ensamblador MIPS
Publicado por: manurodri189 en Sábado 13 de Junio de 2009, 20:22
Lo comentamos pero no me cuadra, si yo quiero que sean caracteres?

Como habria que hacer para imprimirlo entonces? un bucle que imprimar caracter a caracter? o como?

Salu2

Edito: me refiero a que si yo en vez de letras meto numeros, tal que 22233 la codificacion se imprimiria como:

#2#3 siendo la# caracter extraño

y la decodificacion me la hace bien, y tambien imprime numeros.
Título: Re: RLE en ensamblador MIPS
Publicado por: m0skit0 en Sábado 13 de Junio de 2009, 21:05
Código: Text
  1. almacenar_salida:
  2.     la $a0,encode1
  3.     la $a1,encode2
  4.     la $a3,encode
  5.  
:ph34r:  :ph34r:  :ph34r:  veo que no quieres comprender cómo pasar parámetros a las funciones. Esto no va aquí, sino en la llamada a la función. Pero bueno, si no quieres hacer caso, tú mismo :P

Cita de: "manurodri189"
Y es a la hora de imprimir encode, y solo encode, porque los numeros me los imprime como caracteres extraños

Tienes una ligera confusión sobre caracteres y valores. Lo que has escrito en encode1 son caracteres, independientemente de que representen números, letras, puntuaciones o ideogramas chinos. Pero en la memoria lo que tienes no es una 'A' o una '@', evidentemente, sino números, valores. En caso de los caracteres es el código ASCII (http://en.wikipedia.org/wiki/Ascii_code). Por tanto la llamada del sistema de impresión de cadenas de caracteres relaciona cada código con el carácter que el corresponda (un dibujo al fin y al cabo) y lo imprime. Si queremos podemos cambiar las correspondencias código-carácter e incluso usar otros caracteres en vez de los estándar.

Pero si usamos encode2 en la llamada al sistema de impresión de cadenas de caracteres, tenemos un problema, porque lo que hay en memoria son números, no caracteres. Si le sumas a cada elemento de encode2 0x30 antes de imprimirlo, verás cómo sí que funciona bien  :blink:  A ver si sabes por qué...  ;)

PD: y lo que dices que se ve 00 02 en los cuadraditos... ¡qué misterio! :lol: Son caracteres Unicode para los que tu sistema no encuentra fuente, por tanto te pone el código. Y como puedes ver son los números, pero no los caracteres (como te he explicado más arriba).
Título: Re: RLE en ensamblador MIPS
Publicado por: manurodri189 en Sábado 13 de Junio de 2009, 21:22
Cierto tio, me cuesta aprender, no es que no te haga caso xDDDD ahora lo cambio.

Si le sumo 0x30 a cada numero antes de almacenarlo dices que lo imprime, tiene que ser porque en Hexadecimal el 32, es el 2, y el 36, el 6 y así, no?

Solamente tendria que meter la sentencia addiu aqui?

Código: ASM
  1. beq $t3,$zero,finwhile    #si es el caracter vacio acabo
  2.     nop
  3.     addiu $t4,$zero,0x30         #sumo 30 para luego poder imprimirlo
  4.     sb $t4,0($t2)              #cargo el primer numero en encode
  5.     addiu $t2,$t2,1             #avanzo el puntero de encode
  6.     sb $t3,0($t2)              #cargo el caracter en encode
  7.  
  8.  

La salida es esta:

Citar
Entrance String: aaaabbbccc

 String encode like: 0a0b0c

 String decode like: aaaabbbccc

Porque me imprime 0s cuando tiene que imprimr los numeros correspondientes? supongo  que la 0x30 no se puede sumar asi, verdad? como se le suma?

Salu2
Título: Re: RLE en ensamblador MIPS
Publicado por: m0skit0 en Sábado 13 de Junio de 2009, 21:28
Ahi estás poniendo un 0x30 en el registro (lo suams con un cero),no sumándole un 0x30  <_<
Título: Re: RLE en ensamblador MIPS
Publicado por: manurodri189 en Sábado 13 de Junio de 2009, 21:40
Dios!!! estoy en la parra.

Pues ya funciona perfectamente tio!!!. Ahora solo me falta traducirlo al ingles y listo.

Te vuelvo a dar las gracias por todo.

Por cierto no me respondiste si eras de las pedroñeras xDDDDD

Venga crack!!! estamos para lo que quieras, si necesitas cualquier cosa ya sabes donde encontrarme.

Salu2
Título: Re: RLE en ensamblador MIPS
Publicado por: m0skit0 en Domingo 14 de Junio de 2009, 11:55
Cita de: "manurodri189"
Pues ya funciona perfectamente tio!!!
Me alegro, aunque no estoy muy seguro de si sabes cómo funciona...  :P

Cita de: "manurodri189"
Por cierto no me respondiste si eras de las pedroñeras xDDDDD
Jajajaja, no, qué va, soy marroquí  :lol:

¡Saludos y suerte!
Título: Re: RLE en ensamblador MIPS
Publicado por: manurodri189 en Domingo 14 de Junio de 2009, 12:49
Cita de: "m0skit0"
Cita de: "manurodri189"
Pues ya funciona perfectamente tio!!!
Me alegro, aunque no estoy muy seguro de si sabes cómo funciona...  :P

Cita de: "manurodri189"
Por cierto no me respondiste si eras de las pedroñeras xDDDDD
Jajajaja, no, qué va, soy marroquí  :lol:

¡Saludos y suerte!

Creo que aunque es la primera vez, le estoy cogiendo la dinámica, y creo que me he enterado de todo. Seguro que si tengo que volver a hacer un programa en MIPS, me costaría menos que esta vez.

Se lo envié ayer al profesor, y dice que esta muy contento con el trabajo, y que si estoy interesado en proyectos de este tipo, una vez que vuelva a España, que podemos trabajar juntos, hacer publicaciones y demás. Pero vamos aunque la idea no me disgusta, cuando vuelva a España tengo muchas cosas que hacer, así que lo rechazaré por el momento, en el futuro quien sabe.

Salu2
Título: Re: RLE en ensamblador MIPS
Publicado por: m0skit0 en Lunes 15 de Junio de 2009, 11:12
Ojo, si no se practica se pierde, como todo.

Saludos y enhorabuena  ^_^