EC/FC - Práctica 9: ESTRUCTURAS DE CONTROL CONDICIONALES Y DE REPETICIÓN

12 de mayo de 2008

Contents

Introducción

Objetivos

Al finalizar esta práctica el estudiante será capaz de:

  • Realizar operaciones if-then-else
  • Realizar bucles tipo while
  • Realiza bucles tipo for

Material necesario

Para la realización de esta práctica se necesita un ordenador personal con Windows o Linux y el simulador SPIM, disponible en http://pages.cs.wisc.edu/~larus/spim.html. Es muy recomendable que e instales este programa en tu ordenador

Evaluación de la práctica

La evaluación de la práctica comenzará antes de asistir al laboratorio. Así, el estudiante deberá reunirse con su compañero de grupo para preparar cada sesión. El trabajo previo a la prá ctica consistirá en un conjunto de actividades que nos prepararán para obtener el máximo provecho de la sesión de laboratorio. El trabajo previo tendrá una valoración variable y se mostrará al profesor de laboratorio en la primera media hora de cada sesión.

El resto de la evaluación de la práctica estará relacionado con el trabajo en la sesión presencial en el laboratorio. Cada apartado, formado por actividades diversas, tendrá una puntuación. Esta puntuación aparecerá indicada junto a cada actividad.

Trabajo previo antes del Laboratorio (3 puntos)

Para poder sacar el máximo partido a la sesión de laboratorio, lee atentamente el siguiente texto y prepara EN UNA HOJA APARTE las respuestas a los ejercicios.

Estructuras de control condicionales

En esta sección se trata la estructura condicional if. Esta estructura evalúa una condición y si se cumple, ejecuta un determinado código; en caso contrario, no hace nada. El programa siguiente intenta evitar que se realice una división por cero (lo que generaría una excepción). Para ello, comprueba si el divisor es distinto de cero antes de realizar la división, y en caso contrario, simplemente devuelve un 0 como resultado. En concreto, el programa propuesto almacena en la variable res el cociente de la división entera de dos números, dato1 y dato2, o un 0 si dato2 es igual a 0.

1  int main ( int argc, char** arg v ) {
2 int dato1=40;
3 int dato2=30;
4 int res;
5
6 res=0;
7 if (dato2!=0) {
8 res=dato1/dato2;
9 }
10 }

Una versión en ensamblador del MIPS32 del anterior programa en C podría ser la siguiente:

  cotrol-if.s
1   .data # zona de datos
2 dato1: .word 40  
3 dato2: .word 30  
4 res: .space 4  
5      
6   .text # zona de instrucciones
7 main: lw $t1, dato1($0) # Carga M[dato1] en $t1
8   lw $t2, dato2($0) # Carga M[dato2] en $t2
9   and $t0, $0, $0 # $t0<-0
10 si: beq $t2, $0, finsi  
11 entonces: div $t1, $t2 # $t1/$t2
12   mflo $t0 # Almacena LO en $t0
13 finsi: sw $t0, res($0) # Almacena $t0 en res

Actividades (3 puntos)

  1. Identifica en el programa en ensamblador la instrucción que evalúa la condición y controla el flujo del programa. Compárala con la condición del programa en lenguaje C. ¿Qué condición evalúa dicha instrucción en el programa en ensamblador? ¿Qué condición evalúa la instrucción if del programa en C? ¿Qué relación hay entre ambas condicionales?
  2. Identifica en el programa ensamblador las instrucciones que corresponden a la estructura if completa (la instrucción que evalúa la condición, más las instrucciones que se ejecutan en caso de cumplirse la condición del if original).
  3. Carga y ejecuta el programa. ¿Qué valor se almacena en la variable res después de su ejecución?
  4. Reemplaza el contenido de dato2 por un 0. ¿Qué valor se almacena en la variable res después de ejecutar de nuevo el programa?

Trabajo en el Laboratorio (7 puntos)

Estructuras de control condicional if - else

Ahora se va a ver cómo se implementa en ensamblador la estructura de control condicional if - else. Crea un fichero con el siguiente fragmento de código que contiene una estructura de control de dicho tipo.

  cotrol-if_else.s
1   .data # zona de datos
2 dato1: .word 30  
3 dato2: .word 40  
4 res: .space 4  
5      
6   .text # zona de instrucciones
7 main: lw $t1, dato1($0) # Carga dato1 en $t1
8   lw $t2, dato2($0) # Carga dato2 en $t2
9 si: bge $t1, $t2, sino # Si $t1>=$t2 ir a sino
10 entonces: sw $t1, res($0) # Almacena $t1 en res
11   j finsi # Ir a finsi
12 sino: sw $t2, res($0) # Almacena $t2 en res
13 finsi:    

Actividades (3 puntos)

  1. ¿Qué hace el programa? Dicho de otra forma, ¿qué valor se almacena en res en función del contenido de las variables dato1 y dato2?
  2. Carga el fichero en el simulador y ejecuta el programa. ¿Qué valor se almacena en res después de ejecutarlo?
  3. Modifica el contenido de la dirección de memoria dato1 para que almacene el valor 67 en lugar del actual 30. Ejecuta de nuevo el programa. ¿Qué valor se almacena ahora en res?
  4. Identifica en el lenguaje máquina generado por el simulador el conjunto de instrucciones que implementan la pseudoinstrucción bge. ¿Cuáles son?
  5. Implementa en ensamblador el siguiente programa escrito en C que calcula el valor absoluto de la resta de dos números.
1  int main ( int argc, char** arg v ) {
2 int dato1=30;
3 int dato2=40;
4 int res;
5
6 if (dato1<=dato2){
7 res=dato1-dato2;
8 }else{
9 res=dato2-dato1;
10 }
11 }

Estructura de control repetitiva while

El siguiente programa en C utiliza una estructura de control while para descubrir el número de caracteres de una cadena dada (que termina con el carácter nulo).

1 int main( int argc, char** arg v ) {
2 char cadena[ ] = ”Hola, ¿como estas?” ; //Faltas
3 int n =0;
4
5 while ( cadena [n]!=0 ) {
6 n++;
7 }
8 }

Una versión en ensamblador del MIPS32 del anterior programa en C podr´ýa ser la siguiente:

  cotrol-while.s
1   .data # zona de datos
2 cadena: .asciiz "hola, como estas"  
3   .align 2  
4 n: .space 4  
5      
6   .text # zona de instrucciones
7 main: andi $t0, $t0, 0 # $t0<-0
8 mientras: lb $t1, cadena($t0) # $t1<-M[cadena+$t0] (un byte)
9   beq $t1, $0, finmientras # Si $t1>==0 ir a finmientras
10   j mientras  
11 finmientras: sw $t0,n($0) # Almacena $t0 en n

Actividades (2 puntos)

  1. Ejecuta paso a paso el programa anterior y comprueba detenidamente la función de cada una de las instrucciones que constituyen el programa ensamblador.
  2. ¿Qué valor se almacena en n después de ejecutar el programa? ¿Cuántos caracteres tiene la cadena? ¿Se ha contabilizado el carácter nulo?

Estructura de control repetitiva for

La estructura de control repetitiva for se diferencia de la while en que el número de iteraciones de la primera es conocido de antemano. Así pues, se hace necesario el uso de una variable que almacene el número de iteraciones que se van realizando para así poder compararlo con el número de iteraciones que deben realizarse. La variable que almacena dicha cuenta recibe el nombre de contador. Generalmente, un contador se suele inicializar con el valor 0 e incrementar de 1 en 1 hasta que alcanza el número total de iteraciones menos 1.

El siguiente ejemplo muestra un programa en C que acumula los elementos de un vector V en una variable llamada res. Para ello, utiliza una estructura condicional for y un contador llamado i. :

1 int main ( int argc, char** argv ) {
2 int V[]={6, 7, 8, 9, 10, 1};
3 int n =6;
4 int i;
5 int res;
6
7 res=0;
8 for (i=0; i<n; i++) {
9 res=res+V[i];
10 }
11 }

Una versión en ensamblador del MIPS32 del anterior programa en C podría ser la siguiente:

  cotrol-while.s
1   .data # zona de datos
2 vector: .word 6, 7, 8, 9, 10, 1  
3 n: .word 6  
4 res: .space 4  
5      
6   .text # zona de instrucciones
7 main: la $t2, vector # $t2<-dirección de vector
8   and $t3, $0, $0 # t3 <-0
9   and $t0, $0, $0 # t0 <-0
10   lw $t1, n($0) # t1 <-Mem[n]
11   j mientras  
12 para: bge $t0, $t1, finpara # Si $t0>=$t1 Salta a finpara
13   add $t3, $t3, $t4  
14   addi t2, $t2, 4  
15   addi $t0, $t0, 1  
16   j para  
17 finpara: sw $t3,res($0) # Almacena $t3 en res

Actividades (2 puntos)

  1. Ejecuta paso a paso el programa y comprueba detenidamente la función que realizan cada una de las instrucciones que componen el programa en ensamblador.
  2. ¿En qué posición de memoria está la variable res?
  3. ¿Qué valor se almacena en res después de ejecutar el código anterior?
  4. ¿Qué registro se ha utilizado para actualizar el contador? ¿Qué valor posee al finalizar la ejecución dicho registro? ¿Cuántas veces se ha ejecutado el bucle que comienza en la instrucción etiquetada con para?