Programación General > ASM (Ensamblador)

 RLE en ensamblador MIPS

<< < (13/17) > >>

manurodri189:
Bueno he seguido trabajando, y creo que ya he acabado el programa, pero obviamente no funciona, te pego el código.


--- Código: ASM ---.dataEntrance: .space 80Entranceaux: .space 80encode1: .space 40encode2: .space 40encode: .space 40decode: .space 80msg1: .asciiz "Please insert the String: "msg2: .asciiz " "msg3: .asciiz "n String encode like: "msg4: .asciiz "n String decode like: ".text.globl main ## Main#main:    ori $v0,$zero,4    la $a0,msg1    syscall #Almacenar el String en la matriz# Número de syscall    ori $v0,$zero,8# $a0 = buffer para guardar la cadena    la $a0,Entranceaux# $a1 = tamaño a leer    ori $a1,$zero,80    syscall #quitar el ultimo caracter de entrance. la $a0,Entrance         #Almaceno la entrada sin el caracter "enter"la $a1,Entranceaux      #Cadena de entradala $a2,Entranceaux+1´   #puntero al segundo caracter de la cadena de entrada recorrer:    beq $a2, $zero, imprimir    lbu $a0,0($a1)      #meto el caracter     #avanzo todos los punteros    addiu $a2,$a2,1    addiu $a0,$a0,1    addiu $a1,$a1,1         j recorrer  imprimir: #Imprimir la matriz# Número de syscall    ori $v0,$zero,4# $a0 = buffer a imprimir    la $a0,Entrance    syscall ## Codificar#start:    la $s0, Entrance    la $s3, encode1  #almaceno la direccion de encode1 en s3, s3 es el puntero    la $s4, encode2  #almaceno la direccion de encode2 en s4, s4 es el puntero    or $a3,$zero,$s3    or $a2,$zero,$s4 sig_carac:    lbu $s1, 0($s0)    beq $s1, $zero, fin   # Si es el carácter de final de cadena, ya terminamos    add $a0,$zero,$s1     # Pasando el primer parámetro a la función procesar()        jal procesar          # Llamamos a la función procesar()    addiu $a1,$s0,1       # Pasando el segundo parámetro a la función procesar()        add $a0,$zero,$s1  #El carácter en $a0    jal almacenar     # Llamamos a la función almacenar()    add $a1,$zero,$v0  # Ponemos el número de caracteres en $a1        beq $zero,$zero,sig_carac  # Siguiente carácter diferente    or $s0, $zero, $v1        # Actualizamos el puntero con el valor devuelto ## Exit#fin:     jal almacenar_salida     #Imprimir la matriz de salida codificada    # Número de syscall    ori $v0,$zero,4    # $a0 = buffer a imprimir    la $a0,encode    syscall     jal decodificar     #Imprimir la matriz de salida decodificada    # Número de syscall    ori $v0,$zero,4    # $a0 = buffer a imprimir    la $a0,decode    syscall     ori $v0,$zero,10   # Terminamos con exit    syscall ## Procesar (habría que poner un nombre más explicativo :)## Recibe un carácter y el puntero a una cadena# Cuenta cuántos caracteres iguales al pasado consecutivos hay en la cadena# Devuelve en $v0 el número de caracteres iguales# y en $v1 el puntero al primer carácter diferente encontradoprocesar:    add $v0, $zero, $zero   # Inicializamos valores de retorno    add $v1, $zero, $a1    add $t1, $zero, $zero   # Contador de caracteres iguales consecutivosprocesar_iguales:    lbu $t0, 0($a1)                    # Cargamos el siguiente carácter a comparar    bne $a0, $t0, procesar_noiguales   # Si no son iguales, terminamos    addiu $a1, $a1, 1                  # Apuntamos al siguiente carácter        beq $zero, $zero, procesar_iguales    addiu $t1, $t1, 1                  # Si son iguales, aumentamos el contador en uno procesar_noiguales:    add $v0, $v0, $t1   # Ponemos los valores de retorno    add $v1, $v1, $t1  # Volvemos de la función    jr $ra    nop  almacenar:     sb $a0,0($a3)   #meto el caracter en la primera direccion de a3    sb $a1,0($a2)   #meto el contador en la primera direccion de a4     #avanzo el puntero     addiu $a3,$a3,1    addiu $a2,$a2,1   # Volvemos de la función    jr $ra    nop almacenar_salida:    la $a0,encode1    la $a1,encode2    la $a3,encode while:     beq $a0,$zero,finwhile    #si es el caracter vacio acabo    lbu $a3,0($a1)              #cargo el primer numero en encode    addiu $a3,$a3,1             #avanzo el puntero de encode    lbu $a3,0($a0)              #cargo el caracter en encode     #avanzo todos los punteros    addiu $a3,$a3,1    addiu $a0,$a0,1    addiu $a1,$a1,1     j while                   #llamo a while de nuevo  finwhile: # Volvemos de la función    jr $ra    nop  decodificar:     la $a0,encode1    la $a1,encode2    la $a3,decode while2:     beq $a0,$zero,finwhile2    #si es el caracter vacio acabo    lbu $a3,0($a0)             #cargo el caracter en decode    addiu $a3,$a3,1            #avanzo el puntero decode    addiu $a1,$a1,-1           #a1-1 #le resto 1 al primer numero    bnez $a1,while2            #repito el while2 si $a1 es distinto de 0     #avanzo todos los punteros    addiu $a3,$a3,1    addiu $a0,$a0,1    addiu $a1,$a1,1     j while2      finwhile2: # Volvemos de la función    jr $ra    nop 
Ahora vayamos por partes, y a ver si estoy en el buen camino de lo que se me ha ocurrido:


--- Código: ASM ---#Almacenar el String en la matriz# Número de syscall    ori $v0,$zero,8# $a0 = buffer para guardar la cadena    la $a0,Entranceaux# $a1 = tamaño a leer    ori $a1,$zero,80    syscall #quitar el ultimo caracter de entrance. la $a0,Entrance         #Almaceno la entrada sin el caracter "enter"la $a1,Entranceaux      #Cadena de entradala $a2,Entranceaux+1´   #puntero al segundo caracter de la cadena de entrada recorrer:    beq $a2, $zero, imprimir    lbu $a0,0($a1)      #meto el caracter     #avanzo todos los punteros    addiu $a2,$a2,1    addiu $a0,$a0,1    addiu $a1,$a1,1         j recorrer 
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 ---almacenar_salida:    la $a0,encode1    la $a1,encode2    la $a3,encode while:     beq $a0,$zero,finwhile    #si es el caracter vacio acabo    lbu $a3,0($a1)              #cargo el primer numero en encode    addiu $a3,$a3,1             #avanzo el puntero de encode    lbu $a3,0($a0)              #cargo el caracter en encode     #avanzo todos los punteros    addiu $a3,$a3,1    addiu $a0,$a0,1    addiu $a1,$a1,1     j while                   #llamo a while de nuevo  finwhile: # Volvemos de la función    jr $ra    nop 
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 --- decodificar:     la $a0,encode1    la $a1,encode2    la $a3,decode while2:     beq $a0,$zero,finwhile2    #si es el caracter vacio acabo    lbu $a3,0($a0)             #cargo el caracter en decode    addiu $a3,$a3,1            #avanzo el puntero decode    addiu $a1,$a1,-1           #a1-1 #le resto 1 al primer numero    bnez $a1,while2            #repito el while2 si $a1 es distinto de 0     #avanzo todos los punteros    addiu $a3,$a3,1    addiu $a0,$a0,1    addiu $a1,$a1,1     j while2      finwhile2: # Volvemos de la función    jr $ra    nop 
Y luego para decodificar, pues directamente, si el puntero a la matriz de caracter es el de final de cadena, acabo, si no, lo que hago es decrementar el primer numero de la matriz de numeros, y meter el caracter en la matriz final, avanzo el puntero de la matriz final, y vuelvo a hacer el while. Asi hasta que sea 0, entonces avanzo todos los punteros y otra vez a empezar.

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

Salu2

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

m0skit0:
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 ---# void EliminarEnter(char* entrada)eliminar_enter:    li $t1,0xAee_bucle:    lbu $t0,0($a0)    beq $t0,0xA,fin_ee    addiu $a0,$a0,1    beq $zero,$zero,ee_bucle    nopfin_ee:    jr $ra    sb $zero,-1($a0) Y para llamar a la función (evidente, pero lo pongo iwalmente):


--- Código: Text ---la $a0,entrancejal eliminar_enternop Teniendo en cuenta que hemos guardado la cadena en entrance y no en entranceaux, que como ya te dije, sobra.

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

manurodri189:
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 ---.dataEntrance: .space 80encode1: .space 40encode2: .space 40encode: .space 40decode: .space 80msg1: .asciiz "Please insert the String: "msg2: .asciiz " "msg3: .asciiz "n String encode like: "msg4: .asciiz "n String decode like: ".text.globl main ## Main#main:    ori $v0,$zero,4    la $a0,msg1    syscall #Almacenar el String en la matriz# Número de syscall    ori $v0,$zero,8# $a0 = buffer para guardar la cadena    la $a0,Entrance# $a1 = tamaño a leer    ori $a1,$zero,80    syscall la $a0,Entrancejal eliminar_enternop #Imprimir la matriz# Número de syscall    ori $v0,$zero,4# $a0 = buffer a imprimir    la $a0,Entrance    syscall ## Codificar#start:    la $s0, Entrance    la $s3, encode1  #almaceno la direccion de encode1 en s3, s3 es el puntero    la $s4, encode2  #almaceno la direccion de encode2 en s4, s4 es el puntero    or $a3,$zero,$s3    or $a2,$zero,$s4 sig_carac:    lbu $s1, 0($s0)    beq $s1, $zero, fin   # Si es el carácter de final de cadena, ya terminamos    add $a0,$zero,$s1     # Pasando el primer parámetro a la función procesar()        jal procesar          # Llamamos a la función procesar()    addiu $a1,$s0,1       # Pasando el segundo parámetro a la función procesar()        add $a0,$zero,$s1  #El carácter en $a0    jal almacenar     # Llamamos a la función almacenar()    add $a1,$zero,$v0  # Ponemos el número de caracteres en $a1        beq $zero,$zero,sig_carac  # Siguiente carácter diferente    or $s0, $zero, $v1        # Actualizamos el puntero con el valor devuelto ## Exit#fin:     jal almacenar_salida     #Imprimir la matriz de salida codificada    # Número de syscall    ori $v0,$zero,4    # $a0 = buffer a imprimir    la $a0,encode    syscall     jal decodificar     #Imprimir la matriz de salida decodificada    # Número de syscall    ori $v0,$zero,4    # $a0 = buffer a imprimir    la $a0,decode    syscall     ori $v0,$zero,10   # Terminamos con exit    syscall ## Procesar (habría que poner un nombre más explicativo :)## Recibe un carácter y el puntero a una cadena# Cuenta cuántos caracteres iguales al pasado consecutivos hay en la cadena# Devuelve en $v0 el número de caracteres iguales# y en $v1 el puntero al primer carácter diferente encontradoprocesar:    add $v0, $zero, $zero   # Inicializamos valores de retorno    add $v1, $zero, $a1    add $t1, $zero, $zero   # Contador de caracteres iguales consecutivosprocesar_iguales:    lbu $t0, 0($a1)                    # Cargamos el siguiente carácter a comparar    bne $a0, $t0, procesar_noiguales   # Si no son iguales, terminamos    addiu $a1, $a1, 1                  # Apuntamos al siguiente carácter        beq $zero, $zero, procesar_iguales    addiu $t1, $t1, 1                  # Si son iguales, aumentamos el contador en uno procesar_noiguales:    add $v0, $v0, $t1   # Ponemos los valores de retorno    add $v1, $v1, $t1  # Volvemos de la función    jr $ra    nop  almacenar:     sb $a0,0($a3)   #meto el caracter en la primera direccion de a3    sb $a1,0($a2)   #meto el contador en la primera direccion de a4     #avanzo el puntero     addiu $a3,$a3,1    addiu $a2,$a2,1   # Volvemos de la función    jr $ra    nop almacenar_salida:    la $a0,encode1    la $a1,encode2    la $a3,encode while:     beq $a0,$zero,finwhile    #si es el caracter vacio acabo    lbu $a3,0($a1)              #cargo el primer numero en encode    addiu $a3,$a3,1             #avanzo el puntero de encode    lbu $a3,0($a0)              #cargo el caracter en encode     #avanzo todos los punteros    addiu $a3,$a3,1    addiu $a0,$a0,1    addiu $a1,$a1,1     b while                   #llamo a while de nuevo  finwhile: # Volvemos de la función    jr $ra    nop  decodificar:     la $a0,encode1    la $a1,encode2    la $a3,decode while2:     beq $a0,$zero,finwhile2    #si es el caracter vacio acabo    lbu $a3,0($a0)             #cargo el caracter en decode    addiu $a3,$a3,1            #avanzo el puntero decode    addiu $a1,$a1,-1           #a1-1 #le resto 1 al primer numero    bnez $a1,while2            #repito el while2 si $a1 es distinto de 0     #avanzo todos los punteros    addiu $a3,$a3,1    addiu $a0,$a0,1    addiu $a1,$a1,1     b while2      finwhile2: # Volvemos de la función    jr $ra    nop # void EliminarEnter(char* entrada)eliminar_enter:    li $t1,0xAee_bucle:    lbu $t0,0($a0)    beq $t0,0xA,fin_ee    addiu $a0,$a0,1    beq $zero,$zero,ee_bucle    nopfin_ee:    jr $ra    sb $zero,-1($a0) 
He cambiado las j por b, como me has dicho que usa branches y no jumps. Pero sigue sin ir, es posible que la logica esté mal? o son las intrucciones? aunque creo que la lógica es la correcta. Muchas gracias.

Salu2

m0skit0:
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 ---fin:     jal almacenar_salida     #Imprimir la matriz de salida codificada    # Número de syscall    ori $v0,$zero,4    # $a0 = buffer a imprimir    la $a0,encode    syscall está mal, puesto que ori $v0,$zero,4 se ejecuta antes de jal almacenar_salida, y al volver de la función caes en la $a0,encode. Y así todos los siguientes.

manurodri189:
Ok, entiendo se me pasó poner nop detras de la instruccion, con uno seria suficiente, no?

Salu2

PD: sigue sin tirar.

Navegación

[0] Índice de Mensajes

[#] Página Siguiente

[*] Página Anterior

Ir a la versión completa