Mostrando entradas con la etiqueta Ensamblador. Mostrar todas las entradas
Mostrando entradas con la etiqueta Ensamblador. Mostrar todas las entradas

lunes, 9 de febrero de 2015

Ejercicios de ensamblador en MIPS

¿Qué pasa gente? Demasiado tiempo sin publicar nada...
Hoy traigo unos ejercicios en MIPS de unos alumnos de Electrónica, Robótica y Mecatrónica. Os los voy poniendo:

El primero dice asi:
Diseña un programa ensamblador que defina el vector de enteros de dos elementos V=(10,20) en la memoria de datos a partir de la dirección 0x10000000 y almacene su suma a partir de la dirección donde acaba el vector.
.data 0x10000000
vector: .word 10, 20 # Vector de elementos
res: .word 0  # Donde guardaremos el resultado
.text

 addi $8, $0, 4   # Guardo un 4 para pedir la segunda palabra del vector.
 lw $9, vector($0)
 lw $10, vector($8)
 
 add $11, $9, $10  # Sumamos en un temporal el resultado
 sw $11, res($0)   # Guardamos en memoria el resultado.
 
 li $2, 10
 syscall
Por aquí el segundo:
Diseña un programa ensamblador que divida los enteros 18,-1215 almacenados a partir de la dirección 0x10000000 entre el número 5 y que a partir de la dirección 0x10010000 almacene el cociente de dichas divisiones.

.data 0x10000000
entero1: .word 18
entero2: .word -1215
.data 0x10010000
res1: 0
res2: 0

.text
 addi $5, $0, 5
 # Primero un numero y luego el otro.
 lw $8, entero1($0)
 div $9, $8, $5
 sw $9, res1($0)
 
 # Ahora el segundo.
 lw $8, entero2($0)
 div $9, $8, $5
 sw $9, res2($0)
 
 li $2, 10
 syscall
 

El tercero lo he hecho usando una función AND y un número que en binario es todo unos excepto los bits que quiero poner a 0
Pon a cero los bits 3,7,9 del entero 0xabcd12bd almacenado en memoria a partir de la dirección 0x10000000, sin modificar el resto.
.data 0x10000000
valor: .word 0xabcd12bd
.text 
 addi $8, $0, 0xDD7FFFFF   
 lw $9, valor($0)
 and $10, $8, $9
 sw $10, valor($0)
 
 li $2, 10
 syscall

Y el cuarto ejercicio (es el sexto en la relación, pero los anteriores tampoco tenían mucha dificultad) dice tal que así:
Diseña un programa en ensamblador que defina un vector de enteros, V, inicializado según los siguientes valores (V=[2, -4, -6]). Y obtenga un vector de booleanos, tal que cada elemento será 1 si el correspondiente elemento en el vector de enteros es mayor o igual que cero y 0 en caso contrario.

.data 0x10000000
vector: .word 2, -4, -6
tam: .word 3
res: .word -1, -1, -1
.text 
 addi $2, $0, 1   # Constante 1 
 add $6, $0, $0  # Indice del array
 add $7, $0, $0  # Contador
 lw $8, tam($0)  # Tamaño a llegar
loop: 
 lw $9, vector($6) #Elemento del vector
 slt $10, $9, $0  # Si el segundo es menor que el tercero, el primero vale 1
 beq $10, $0, esPositivo
 # Si sigue por aquí es negativo
 sw $0, res($6)
 j vuelta
 
esPositivo:
 sw $2, res($6)
 j vuelta 
 
vuelta: addi $7, $7, 1
 addi $6, $6, 4
 bne $7, $8 loop
 
 li $2, 10
 syscall
 

Eso es todo. Espero que os sirvan. Si tenéis alguna duda comentadla.

Saludos;)

miércoles, 11 de junio de 2014

Ejercicios de ensamblador MIPS: funciones (sumatorio, factorial), media aritmética ...

Vuelvo con ejercicios de ensamblador MIPS.
En estos ejercicios ya vemos el uso de funciones, y por tanto de las instrucciones jal y jr. Recuerdo que es recomendable, aunque más bien necesario, echar un vistazo a las instrucciones para conocerlas bien y si no tenéis ni idea de ensamblador MIPS recomiendo visitar la anterior entrada en la que os dejé unos ejemplos muy sencillos para entender las instrucciones más usuales.

NOTA: Aunque en algunos ejercicios piden una función, para poder probarla añado un "main" y un segmento de datos de prueba. Pero recordad que la función debe funcionar independientemente de esos datos.

Función factorial en ensamblador MIPS.
# función factorial (argumento en $a1, valor devuelto en $v1)
# número en 'ene'
# valor factorial en 'resul'


.data
ene:      .word  5
             .space 28
resul:    .word  0        

      
.text
main:    lw $a1,ene($0)
         jal  fact          
         sw $v1,resul($0)               
         li $v0,10
         syscall
          
fact:
       addi $v1, $0, 1
       add $8, $a1, $0
      
loop:
  beq $8, $0, fin  
 mul $v1, $v1,$8
        subi $8, $8, 1
        j loop
     
fin:  jr $31


Realizad una función llamada ‘sumatorio” que sume las componentes de un vector de números enteros almacenados en memoria. Los parámetros de entrada a la función son, la dirección de comienzo del vector en $a0 y el número de componentes en $a1. La función devuelve el valor de la suma en $v0.
.data
suma: .word 0
.space 24
tamano: .word 10
datos1: .word 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
 .word 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32

.text
main:  la $a0, datos1
 lw $a1, tamano($0)
 jal sumatorio
 sw $v0, suma($0)
 li $2, 10
 syscall 

sumatorio:  add $10, $0, $0 # inicializo 10
  add $v0, $0, $0 # inicializo 8
  
etq1:  lw $9, 0($a0)
  add $v0,$v0,$9 
  addi $a0,$a0,4 
  addi $10,$10, 1 
  bne $10,$a1,etq1 
  jr $ra


A partir de la posición de memoria etiquetada como ‘A’ hay almacenada una secuencia de ‘n’ números. El valor ‘n’ se encuentra almacenado en la posición previa a ‘A’. Realizad un programa que lea dicha secuencia y la transforme en otra que se almacene a partir de la posición etiquetada como ‘B’ y obedezca la siguiente expresión de transformación:
B(0)=A(0)
B(i)= (A(i)+A(i-1))/2                i=1,2,...,n-1
Utilizad la cabecera de programa que se indica a continuación.

.data
       .space 28
       .word 5
A:     .word 2,4,5,7,4,9,6,8,9,4,5,6,7,8,9,3,4,5,9,7,2,3,4,777
B:     .word 0
      


.text  
 addi $10, $0, -4
 lw $10, A($10) # en el registro 10 tengo n
 
 beq $10, $0, fin
 
 slt $15, $10, $0
 
 bne $15, $0, fin 
 
 add $9, $0, $0
 
 
 lw $8,A($9) # En el registro 8, A
 lw $11, B($9) # En el registro 11, B
 
 sw $8, B($0) # B(0) = A(0)
 
 addi $14, $10, -1
 
loop: addi $9, $9, 4 # incrementar puntero
 
 addi $10, $9, -4
 
 lw $12, A($10)
 lw $8,A($9) 
 
 add $13, $8, $12
 
 div $13, $13, 2
 
 sw $13, B($9) 
 
 addi $14, $14, -1
 
 
 bne $14, $0, loop
 
fin: li $2, 10
 syscall
   


A partir de la posición de memoria etiquetada como ‘datos’ hay almacenada una secuencia de ‘n’ números. El valor ‘n’ se encuentra almacenado en la posición previa a ‘datos’. Realizad un programa que calcule la media aritmética de dicha secuencia y la almacene en la posición etiquetada como ‘med’. Utilizad la cabecera de programa que se indica a continuación.
.data 
 .space 28 
 .word 5
datos: .word 2,4,5,7,4,95,6,8,9,4,555,6,7,8,9,3,4,5,9,7,2,3,4,777 
med: .word 0 


.text 

addi $9, $10, -4
lw $9, datos($9) # tengo n en $9

slti $13, $9, 1


add $10, $0, $0
add $11, $0, $0
add $12, $0, $0

bne $0, $13, fin

suma:
lw $8, datos($12)
add $11, $11, $8
addi $10, $10, 1
addi $12, $12, 4
bne $10, $9, suma
div $11, $11, $9
sw $11, med($0)
fin:
li $2, 10
syscall

viernes, 30 de mayo de 2014

Ejemplos de introducción: ENSAMBLADOR MIPS.

Empezamos con la programación en ensamblador MIPS con esta entrada que contiene unos ejemplos bastante sencillitos para empezar. Si no se sabe nada acerca del repertorio de instrucciones de MIPS es recomendable leer algo acerca de ellas, al menos qué es lo que hacen, pues si no os será imposible realizar los ejercicios posteriores de una complejidad mayor.

Os dejo tres ejemplos básicos para empezar a conocer las instrucciones más usuales add, lw, sw, beq, j... En la próxima entrada serán un poco más difíciles ;)

Suma de dato1 y dato1 almacenada en la variable sum.
.data
dato1:	.word 2				
dato2:	.word 5				
sum:	.word 0				

.text
main:	lw $8, dato1($0)		# cargamos el primer dato en el registro $8
	lw $9, dato2($0)		# cargamos el segundo dato en el registro $9
	add $10, $8, $9			# sumamos los dos registros y el resultado lo almacenamos en $10
	sw $10, sum($0)			# almacenamos el resultado ($10) en su variable (sum)
	
fin:	li $2, 10			# cargamos parametro necesario para terminar programa
	syscall				# llamada al sistema que termina un programa

Escribir en la variable max el valor máximo contenido en las variables dato1 y dato2.
.data
dato1:	.word 2				
dato2:	.word 5				
max:	.word 0				

.text
main:		lw $8, dato1($0)	
		lw $9, dato2($0)	
		slt $10, $8, $9		
		beq $10, $0, d1		
		sw $9, max($0)		
		j fin				
d1:		sw $8, max($0)		
fin:		li $2, 10			
		syscall	

Suma de los valores almacenados en un vector.
.data
tam: .word 8
datos: .word 2, 4, 6, 8, -2 -4, -6 -7
res: .word 0
.text
main:  lw $8, tam($0)
  la $9, datos
  sub $11, $11, $11
loop:  lw $10, 0($9)  
  add $11, $11, $10
  addi $9, $9, 4
  addi $8, $8, -1
  beq $8, $0, salir
  j loop
salir:  sw $11, res($0)
  li $2, 10
  syscall