Programación General > ASM (Ensamblador)
RLE en ensamblador MIPS
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
[#] Página Siguiente
[*] Página Anterior
Ir a la versión completa