Está en la página 1de 5

Prácticas de Estructura de Computadores –Grado en Ingeniería Informática Curso 2016/17

PRÁCTICA 3
Programación en ensamblador MIPS. Procedimientos I

Objetivos:

 Iniciarse en la programación estructurada en ensamblador del MIPS.


 Aprender a manejar los procedimientos: definición, llamada y retorno.
 Manejar las llamadas al sistema operativo desde un programa en ensamblador.

Desarrollo / Comentario:

Paso de parámetros por valor. Para el paso de parámetros por valor, antes de realizar la llamada a la
subrutina, el programa principal carga el valor de los parámetros de entrada en los registros elegidos
para ello.

Paso de parámetros por referencia. Para el paso de parámetros por referencia, antes de realizar la
llamada a la subrutina, el programa principal carga en los registros elegidos para ello las direcciones de
memoria en las que está almacenada la información.

 Escribir en ensamblador MIPS32 un programa equivalente al siguiente programa en C.

int main()
{ int a[8]={0x50,0x60,0x70,0,0,0,0,0x90};
int b[8]={1,3,5,7,9,11,13,15};
int c[8]={2,4,6,8,0x10,0x12,0x14,0x16};
int v1[8];
int v2[8];
int sumando;

sumando=Suma_vectores (a,b,v1,8);
printf(“%d”,sumando);
sumando=Suma_vectores (b,c,v2,4);
printf(“%d”,sumando);
return 0;

int Suma_vectores (int *a,int *b, int *c, int dim_vec )


{
int i,sumando=0;
for (i=0;i<dim_vec; i++)
{
c[i]=a[i]+b[i];
sumando=sumando+c[i];
}
return(sumando);

}
Prácticas de Estructura de Computadores –Grado en Ingeniería Informática Curso 2015/16

Nota: Los registros $a0 - $a3 se usarán para pasar los argumentos. Los registros $v0 - $v1 se usarán para el retorno de
valores. Si hay que usar más registros (como argumentos o como retorno) se pasarán por la pila.

Los registros $t0 - $t9 se usarán como registros temporales y no será necesario que el procedimiento preserve su valor. Los
registros $s0 - $s7 deberán preservar su valor, es decir el procedimiento los apilará al comienzo de su ejecución y los
desapilará justo antes de retornar.

Anexo: Llamadas al sistema

El simulador usado en las prácticas, Simula3MS, ofrece un pequeño conjunto de servicios de llamada al sistema
operativo a través de la instrucción de llamada al sistema (syscall).

Para realizar una llamada al sistema (Tabla 1) se cargará en el registro $v0 el código de la llamada y en los registros
$a0 y $a1 (o $f12 para valores de punto flotante) los argumentos.

Las llamadas al sistema que devuelven valores ponen sus resultados en el registro $v0 (o $f0 para resultados de punto
flotante).

Existen llamadas al sistema para salida de datos:

 print_int muestra en el diálogo como un entero el valor entero que se le pasa

 print_float muestra en el diálogo el valor en punto flotante que se le pasa.

 print_double hace lo mismo que print_float pero permite un rango más amplio de números en punto flotante.

 print_string muestra en el diálogo la cadena almacenada a partir de la dirección que indica $a0 hasta que
encuentra el carácter de finalización de cadena.

También hay llamadas al sistema para entrada de datos, estos datos se solicitan al usuario a través de diálogos:

 read_int almacena el entero que introduce el usuario en $v0.


 read_float almacena el número de punto flotante que le introduce el usuario en el registro $f0 con formato de
simple precisión.
 read_double almacena el número de punto flotante que le introduce el usuario en los registros $f0 y $f1, puesto
que el formato de doble precisión necesita dos registros para almacenar un valor.
 read_string almacena la dirección de comienzo de la cadena que introduce el usuario en el registro $a0 y la
longitud de dicha cadena en $a1.

Otra llamada al sistema muy utilizada es exit, que indica al procesador que se ha terminado la ejecución del programa.

2
Prácticas de Estructura de Computadores –Grado en Ingeniería Informática Curso 2015/16

Código Nombre Operación

1 print_int Imprime como un entero aquello que se encuentra en


$a0.
2 print_float Imprime como un número en punto flotante de
aquello que se encuentra en $f12.
3 print_double Imprime como un número en punto flotante
aquello que se encuentra en $f12 y $f13, considerando
que forman un sólo registro de doble precisión.
4 print_string Imprime como un string aquello que se encuentra
en la posición indicada por $a0.
5 read_int Solicita un entero que se almacenará en el registro $v0.
6 read_float Solicita un número en punto flotante que se almacenará
en el registro $f0 con formato de simple precisión
7 read_double Solicita un número en punto flotante que se almacenará
en el registro $f0 (y $f1) con formato de doble
precisión.
8 read_string Solicita un string que se almacena en $a0 y cuya
longitud se guarda en $a1.
10 exit Finaliza la ejecución.
Tabla 1: Códigos asociados a syscall

Ejemplo sencillo:

.text
.globl main
main:
li $v0, 4
la $a0, str
syscall # print string

li $v0, 10
syscall # exit

.data
str: .asciiz "Hola Mundo!!!"

3
Prácticas de Estructura de Computadores –Grado en Ingeniería Informática Curso 2015/16

.data
#declaramos la variables
a: .word 0x50, 0x60, 0x70, 0, 0, 0, 0, 0x090 #array a, cuidado con 0x090
b: .word 1, 3, 5, 7, 9, 11, 13, 15 #array b
c: .word 2, 4, 6, 8, 0x10, 0x12, 0x14, 0x16 #array c
v1: .space 32 # 8 posiciones x4 bytes
v2: .space 32 # 8 posiciones x4 bytes

# creamos el programa
.text
.globl main
main:
#primera muestra por pantalla
#recogemos lo que necesitamos para la primera salida a pila:
li $a3, 8 # tamaño numérico del vector
la $a0, a # valor de la variable a
la $a1, b # valor de la variable b
la $a2, v1 # valor de la variable v1

jal acumulador #ponemos a 0 $v0

#mostramos por pantalla


add $a0, $v0, $0 #se suma la evaluación de expresión y resultado de la función + constante 0 en $a0
li $v0, 1 #se pone un 1 en la evaluación de expresión y resultado de la función para que a continuación
se imprima un entero
syscall #se muestra por pantalla

#segunda muestra por pantalla


li $a3, 4 # tamaño numérico del vector
la $a0, b # valor de la variable b
la $a1, c # valor de la variable c
la $a2, v2 # valor de la variable v2

jal acumulador #ponemos a 0 $v0

#mostramos por pantalla


add $a0, $v0, $0 #se suma la evaluación de expresión y resultado de la función + constante 0 en $a0
li $v0, 1 #se pone un 1 en la evaluación de expresión y resultado de la función para que a continuación
se imprima un entero
syscall #se muestra por pantalla

li $v0, 10 #exit
syscall

acumulador:
li $v0, 0 #ponemos $v0 a 0

4
Prácticas de Estructura de Computadores –Grado en Ingeniería Informática Curso 2015/16

bucle:
beq $a3, $0, termina #el bucle termina cuando el tamaño numérico del vector sea 0
lw $t0, 0($a0) #cargamos en el temporal 0 la palabra contenida en la dirección de memoria $a0 +
0"desplazamiento"
lw $t1, 0($a1) #cargamos en el temporal 1 la palabra contenida en la dirección de memoria $a1 +
0"desplazamiento"
lw $t2, 0($a2) #cargamos en el temporal 2 la palabra contenida en la dirección de memoria $a2 +
0"desplazamiento"
add $t2, $t1, $t0 #sumamos en el temporal 2, el temporal 1 mas el temporal 0
add $v0, $v0, $t2 #sumamos en $v0, $v0 + el contenido del temporal 2
addi $a0, $a0, 4 #se abanza de posición en el array de $a0
addi $a1, $a1, 4 #se abanza de posición en el array de $a1
addi $a2, $a2, 4 #se abanza de posición en el array de $a2
addi $a3, $a3, -1 #va reduciendo el tamaño numérico del array
j bucle #se repite el bucle

termina:
jr $ra # volvemos antes del bucle, al jal señalado por ra

También podría gustarte