Hola a todos ,
Primero decir que no se si esto iría aquí exactamente, si no es así por favor que algun moderador mueva el post al foro donde corresponda. Muchas gracias y perdón por las molestias
El caso es que, para un trabajo de clase, nos han pedido hacer un codigo en lenguaje ensamblador usando arquitectura MipsR2000. El problema consiste en meter una cadena que represente números y que la muestre como números por pantalla (usando un terrible simulador llamado PCSPIM).
He hecho el codigo, pero no consigo que funcione, y tengo que tenerlo hecho antes del jueves.
Lo he mirado 1000 veces, cambiado cosas y no tengo ni idea de porque no funciona.
########################################################
# Segmento de datos a partir de la dirección 0x10000000
########################################################
.data 0x10000000
########################################################
# Espacios
########################################################
cadena: .space 13 # para almacenar la cadena - cada numerito es un caracter ASCII y ocupa 1 byte (4 bytes = 1 palabra)
# segun la practica, por el max. nº de Ca2, mas signo y otras cosas es 13 caracteres
resultado: .space 32 # el resultado sera una palabra de 32 bits
########################################################
# Segmento de código a partir de la dirección 0x00400000
########################################################
.globl __start
.text 0x00400000
__start:
la $a0, cadena # Dirección de cadena en $a0
la $t0, resultado # aki se guardara el resultado de la funcion -> t0 = valor = 0 ya esta inicializao con space
# SOBRE READ_STRING (li $v0,8; syscall)
# ---------------------------------------
# Si se especifica una longitud máxima de n, entonces lee hasta n–1 caracteres y termina la
# cadena con el carácter NUL (codificado en ASCII como 0x00); si la cadena de entrada tiene menos
# caracteres entonces se incluye el carácter NL (new line) o retorno de carro (codificado en ASCII
# como 0x0A) y termina la cadena con el carácter NULL
li $a1, 13 # argumento lenght
li $v0,8 # read_string, argumentos: $a0=buffer, $a1=length
syscall # aki se meten los numeros y se almacenan en $a0
jal convertir # Llamada a la subrutina
la $a0, resultado # metemos como argumento del "printf" la solucion de la subrutina
li $v0,1 # print_int, argumentos: $a0 = integer to be printed
syscall # aki se imprime el resultado
########################################################
# Finalización del programa
# Llamada al sistema denominada "exit"
########################################################
li $v0, 10 # Función exit
syscall
########################################################
# Subrutina que convierte una cadena de numeros codificados como caracteres ASCII en su valor numérico en complemento a dos
# Primer argumento: $a0 (dirección de la cadena)
# Resultado: $t0
# Registros temporales:
#######################################################
convertir:
#add $t0, $0, $0 # t0 = valor = 0 -> NOOO, se inicializa arriba con space (espero) - parece ke si
add $t5, $0, $0 # t5 sera 'valor' en la subrutina, y guardara el resultado
lw $t1, 0($a0) # t1 = actual = primer_carácter(cadena);
addi $t2, $t1, -45 # si (actual == '–') # restamos y si da cero eske es ese caracter (el 45 o 2D es el ascii del menos)
beqz $t2, es_negativo # signo = negativo;
addi $t4, $0, 0 # #t4 = indica signo : 0 = positivo, 1 = negativo
j salto # sino signo = positivo;
es_negativo: addi $t4, $0, 1 # si es un menos, se hace printf("-") , ya pensare como )
bucle: addi $a0, $a0, 4 # actual = siguiente_carácter(cadena);
salto:
lw $t1, 0($a0) # t1 = actual
#addi $t2, $t1, -10 # menos 0x0A (caracter retorno carro) - A es el 10
#beqz $t2, fin_cadena # mientras (actual <> NL)
beqz $t1, fin_cadena # ne el programa se puen meter 13 numeros, los ke no se metan se kedan en 0, asike cuando pille cero ke acabe
# valor = (valor * 10) + actual - '0';
addi $t3, $0, 10 # contador de multiplicar * 10
mult10: add $t5, $t5, $t5 # sumamos el mismo numero 10 veces i es como hacer * 10
addi $t3, $t3, -1
bnez $t3, mult10
add $t5, $t5, $t1
addi $t5, $t5, -0x30 # 0x30 es en valor de 0 (cero) de ascii en hex, en dec es 48 (por si acaso lo anoto aki)
j bucle # siempre saltara. si tiene ke acabar, lo ara mas arriba
fin_cadena: bnez $t4, cambio_signo # si (signo == negativo) valor = –valor;
j fin_func
cambio_signo: sub $t5, $0, $t5 # asi resta a cero el valor del registro, ke es el numero resultante, asi tendremos el negativo
fin_func: la $t0, resultado # aki se guardara el resultado de la funcion
sw $t5, 0($t0) # guardamos el resultado de valor en la direccion de 'resultado'
jr $ra
.end
Este es el codigo que he escrito (estara plagado de faltas y errores seguro )
Y esto es lo que me devuelve el programilla:
SPIM Version 6.4 of January 1, 2002
Copyright 1990-2002 by James R. Larus ([email protected]).
All Rights Reserved.
DOS and Windows ports by David A. Carley ([email protected]).
Copyright 1997 by Morgan Kaufmann Publishers, Inc.
See the file README for a full copyright notice.
SPIM Version 6.4 of January 1, 2002
Copyright 1990-2002 by James R. Larus ([email protected]).
All Rights Reserved.
DOS and Windows ports by David A. Carley ([email protected]).
Copyright 1997 by Morgan Kaufmann Publishers, Inc.
See the file README for a full copyright notice.
Memory and registers have been cleared, and the simulator reinitialized.
[0x00400000] 0x3c041000 lui $4, 4096 [cadena] ; 22: la $a0, cadena # Dirección de cadena en $a0
[0x00400004] 0x3c011000 lui $1, 4096 [resultado] ; 23: la $t0, resultado # aki se guardara el resultado de la funcion -> t0 = valor = 0 ya esta inicializao con space
[0x00400008] 0x3428000d ori $8, $1, 13 [resultado]
[0x0040000c] 0x3405000d ori $5, $0, 13 ; 32: li $a1, 13 # argumento lenght
[0x00400010] 0x34020008 ori $2, $0, 8 ; 33: li $v0,8 # read_string, argumentos: $a0=buffer, $a1=length
[0x00400014] 0x0000000c syscall ; 34: syscall # aki se meten los numeros y se almacenan en $a0
[0x00400018] 0x0c10000d jal 0x00400034 [convertir] ; 36: jal convertir # Llamada a la subrutina
[0x00400034] 0x00006820 add $13, $0, $0 ; 61: add $t5, $0, $0 # t5 sera 'valor' en la subrutina, y guardara el resultado
[0x00400038] 0x8c890000 lw $9, 0($4) ; 63: lw $t1, 0($a0) # t1 = actual = primer_carácter(cadena);
[0x0040003c] 0x212affd3 addi $10, $9, -45 ; 66: addi $t2, $t1, -45 # si (actual == '–') # restamos y si da cero eske es ese caracter (el 45 o 2D es el ascii del menos)
[0x00400040] 0x11400003 beq $10, $0, 12 [es_negativo-0x00400040]; 67: beqz $t2, es_negativo # signo = negativo;
[0x00400044] 0x200c0000 addi $12, $0, 0 ; 68: addi $t4, $0, 0 # #t4 = indica signo : 0 = positivo, 1 = negativo
[0x00400048] 0x08100015 j 0x00400054 [salto] ; 69: j salto # sino signo = positivo;
[0x00400054] 0x8c890000 lw $9, 0($4) ; 75: lw $t1, 0($a0) # t1 = actual
[0x00400058] 0x11200008 beq $9, $0, 32 [fin_cadena-0x00400058]; 80: beqz $t1, fin_cadena # ne el programa se puen meter 13 numeros, los ke no se metan se kedan en 0, asike cuando pille cero ke acabe
[0x0040005c] 0x200b000a addi $11, $0, 10 ; 84: addi $t3, $0, 10 # contador de multiplicar * 10
[0x00400060] 0x01ad6820 add $13, $13, $13 ; 86: add $t5, $t5, $t5 # sumamos el mismo numero 10 veces i es como hacer * 10
[0x00400064] 0x216bffff addi $11, $11, -1 ; 87: addi $t3, $t3, -1
[0x00400068] 0x1560fffe bne $11, $0, -8 [mult10-0x00400068]; 88: bnez $t3, mult10
[0x00400060] 0x01ad6820 add $13, $13, $13 ; 86: add $t5, $t5, $t5 # sumamos el mismo numero 10 veces i es como hacer * 10
[0x00400064] 0x216bffff addi $11, $11, -1 ; 87: addi $t3, $t3, -1
[0x00400068] 0x1560fffe bne $11, $0, -8 [mult10-0x00400068]; 88: bnez $t3, mult10
[0x00400060] 0x01ad6820 add $13, $13, $13 ; 86: add $t5, $t5, $t5 # sumamos el mismo numero 10 veces i es como hacer * 10
[0x00400064] 0x216bffff addi $11, $11, -1 ; 87: addi $t3, $t3, -1
[0x00400068] 0x1560fffe bne $11, $0, -8 [mult10-0x00400068]; 88: bnez $t3, mult10
[0x00400060] 0x01ad6820 add $13, $13, $13 ; 86: add $t5, $t5, $t5 # sumamos el mismo numero 10 veces i es como hacer * 10
[0x00400064] 0x216bffff addi $11, $11, -1 ; 87: addi $t3, $t3, -1
[0x00400068] 0x1560fffe bne $11, $0, -8 [mult10-0x00400068]; 88: bnez $t3, mult10
[0x00400060] 0x01ad6820 add $13, $13, $13 ; 86: add $t5, $t5, $t5 # sumamos el mismo numero 10 veces i es como hacer * 10
[0x00400064] 0x216bffff addi $11, $11, -1 ; 87: addi $t3, $t3, -1
[0x00400068] 0x1560fffe bne $11, $0, -8 [mult10-0x00400068]; 88: bnez $t3, mult10
[0x00400060] 0x01ad6820 add $13, $13, $13 ; 86: add $t5, $t5, $t5 # sumamos el mismo numero 10 veces i es como hacer * 10
[0x00400064] 0x216bffff addi $11, $11, -1 ; 87: addi $t3, $t3, -1
[0x00400068] 0x1560fffe bne $11, $0, -8 [mult10-0x00400068]; 88: bnez $t3, mult10
[0x00400060] 0x01ad6820 add $13, $13, $13 ; 86: add $t5, $t5, $t5 # sumamos el mismo numero 10 veces i es como hacer * 10
[0x00400064] 0x216bffff addi $11, $11, -1 ; 87: addi $t3, $t3, -1
[0x00400068] 0x1560fffe bne $11, $0, -8 [mult10-0x00400068]; 88: bnez $t3, mult10
[0x00400060] 0x01ad6820 add $13, $13, $13 ; 86: add $t5, $t5, $t5 # sumamos el mismo numero 10 veces i es como hacer * 10
[0x00400064] 0x216bffff addi $11, $11, -1 ; 87: addi $t3, $t3, -1
[0x00400068] 0x1560fffe bne $11, $0, -8 [mult10-0x00400068]; 88: bnez $t3, mult10
[0x00400060] 0x01ad6820 add $13, $13, $13 ; 86: add $t5, $t5, $t5 # sumamos el mismo numero 10 veces i es como hacer * 10
[0x00400064] 0x216bffff addi $11, $11, -1 ; 87: addi $t3, $t3, -1
[0x00400068] 0x1560fffe bne $11, $0, -8 [mult10-0x00400068]; 88: bnez $t3, mult10
[0x00400060] 0x01ad6820 add $13, $13, $13 ; 86: add $t5, $t5, $t5 # sumamos el mismo numero 10 veces i es como hacer * 10
[0x00400064] 0x216bffff addi $11, $11, -1 ; 87: addi $t3, $t3, -1
[0x00400068] 0x1560fffe bne $11, $0, -8 [mult10-0x00400068]; 88: bnez $t3, mult10
[0x0040006c] 0x01a96820 add $13, $13, $9 ; 90: add $t5, $t5, $t1
[0x00400070] 0x21adffd0 addi $13, $13, -48 ; 92: addi $t5, $t5, -0x30 # 0x30 es en valor de 0 (cero) de ascii en hex, en dec es 48 (por si acaso lo anoto aki)
[0x00400074] 0x08100014 j 0x00400050 [bucle] ; 94: j bucle # siempre saltara. si tiene ke acabar, lo ara mas arriba
[0x00400050] 0x20840004 addi $4, $4, 4 ; 72: addi $a0, $a0, 4 # actual = siguiente_carácter(cadena);
[0x00400054] 0x8c890000 lw $9, 0($4) ; 75: lw $t1, 0($a0) # t1 = actual
[0x00400058] 0x11200008 beq $9, $0, 32 [fin_cadena-0x00400058]; 80: beqz $t1, fin_cadena # ne el programa se puen meter 13 numeros, los ke no se metan se kedan en 0, asike cuando pille cero ke acabe
[0x00400078] 0x15800002 bne $12, $0, 8 [cambio_signo-0x00400078]; 97: bnez $t4, cambio_signo # si (signo == negativo) valor = –valor;
[0x0040007c] 0x08100021 j 0x00400084 [fin_func] ; 98: j fin_func
[0x00400084] 0x3c011000 lui $1, 4096 [resultado] ; 102: la $t0, resultado # aki se guardara el resultado de la funcion
[0x00400088] 0x3428000d ori $8, $1, 13 [resultado]
[0x0040008c] 0xad0d0000 sw $13, 0($8) ; 103: sw $t5, 0($t0) # guardamos el resultado de valor en la direccion de 'resultado'
Exception occurred at PC=0x0040008c
Unaligned address in store: 0x1000000d
El error sale en las ultimas lineas.
No se si me he explicado bien, pero fijo que es una chorrada pero yo es que soy muy burro para estas cosas.
Si algún crack del ensamblador pudiese echarle un ojo rapido, a ver si descubre que error estoy cometiendo, le estaría muy agradecido (el profesor de la asignatura es bastante cabroncete, se niega a ayudar) :qq:
Muchas gracias