EC/FC - Práctica 8: Operaciones de salto condicional y de comparación

15 de Abril de 2008

Contents

Introducción

Objetivos

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

  • Realizar operaciones de salto condicional.
  • Realizar operaciones de comparación.
  • Evaluar condiciones.

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. Eltrabajo 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 conel 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.

Según lo visto hasta ahora, una vez que el procesador ha completado la ejecución de una instrucción, continúa con la ejecución de la siguiente instrucción: aquella que se encuentra en la posición de memoria siguiente a la de la instrucción que acaba de ejecutar. La ejecución de una instrucción tras otra, siguiendo el órden en el que están en memoria, es lo que se denomina ejecución secuencial. Ejemplos de ejecución secuencial son los programas vistos en los capítulos anteriores. Éstos estaban formados por una serie de instrucciones que se debían ejecutar una tras otra, siguiendo el orden en el que se encontraban en memoria, hasta que el programa finalizaba. Sin embargo, este forma de ejecución tiene bastantes limitaciones. Un programa de ejecución secuencial no puede, por ejemplo, tomar diferentes acciones en función de los datos de entrada, o de los resultados obtenidos, o de la interacción con el usuario. Tampoco puede realizar un número n de veces ciertas operaciones repetitivas (a no ser que el programador haya escrito n veces las mismas operaciones; y en este caso, n debería de ser un número predeterminado y no podría variar en sucesivas ejecuciones). Debido a la gran ventaja que supone el que un programa pueda tomar diferentes acciones y que pueda repetir un conjunto de instrucciones un determinado número de veces, los lenguajes de programación proporcionan estructuras de control que permiten llevar a cabo dichas acciones: las estructuras de control condicionales y repetitivas. Estas estructuras de control permiten modificar el flujo secuencial de instrucciones. En particular, las estructuras de control condicionales permiten la ejecución de ciertas partes del código en función de una serie de condiciones. Y las estructuras de control repetitivas permiten la repetici ón de cierta parte del código hasta que se cumpla una determinada condición de parada. Para poder implementar las estructuras de control condicionales y repetitivas, el juego de instrucciones del MIPS32 incorpora un conjunto de instrucciones que permiten realizar saltos condicionales y comparaciones.

Operaciones de salto condicional

El lenguaje máquina del MIPS32 proporciona dos instrucciones básicas de salto condicional: beq (branch if equal, salta si igual) y bne (branch if not equal, salta si distinto). Su sintaxis es la siguiente: beq rs, rt, etiqueta bne rs, rt, etiqueta Ambas instrucciones realizan una comparación de los valores almacenados en los registros rs y rt y dependiendo del resultado de dicha comparación, verdadera o falsa, saltan a la dirección de la instrucción referenciada por la `` etiqueta`` o no. En el caso de la instrucción beq, el resultado de la comparaci ón será verdadero cuando los valores almacenados en ambos registros sean idénticos. En el caso de la instrucción bne, el resultado será verdadero cuando los valores almacenados en ambos registros sean distintos. Además de las instrucciones de salto condicional anteriores, que comparan el contenido de dos registros para decidir si se realiza o no el salto indicado, el procesador MIPS proporciona instrucciones para comparar el contenido de un registro con el número 0. Estas instrucciones son: bgez (branch if greater of equal than zero, salta si mayor o igual que cero), bgtz (branch if greater than zero, salta si mayor que cero), blez (branch if less or equal than zero, salta si menor o igual que cero) y bltz (branch if less than zero, salta si menor que cero). La sintaxis de estas instrucciones de comparación de un registro con el número 0 es: bgez rs, etiqueta bgtz rs, etiqueta blez rs, etiqueta bltz rs, etiqueta Las instrucciones anteriores comparan el contenido del registro rs con el número 0 y saltan a la dirección de la instrucción referenciada por `` etiqueta `` cuando rs>=0 (caso de bgez), rs>0 (bgtz), rs<=0 (blez) y rs<0 (bltz). Las instrucciones beq, bne, bgez, bgtz, blez y bltz, son todas las instrucciones de salto condicional que proporciona el procesador MIPS32. Sin embargo, y para facilitar la programación en ensamblador, el ensamblador del MIPS32 proporciona además las siguientes pseudo-instrucciones: bge rs, rt, etiqueta (salta si rs >= rt) bgt rs, rt, etiqueta (salta si rs > rt) ble rs, rt, etiqueta (salta si rs <= rt) blt rs, rt, etiqueta (salta si rs < rt)

Operaciones de comparación

Conviene introducir aquí un poco de notación. Para representar que el resultado de una comparación se almacena en un registro, se utiliza una expresión similar a: rd <- (rs < rt) (esta expresión en particular, indica que se almacena en rd el resultado de comparar si rs es menor que rt). El resultado de una comparación puede ser verdadero o falso. Para representar en un computador1 el valor verdadero se utiliza el número 1 y para representar el valor falso se utiliza el número 0. Así, rd <- (rs < rt) indica que en el registro rd se almacenará un 1 o un 0 dependiendo de si el resultado de la comparación rs < rt es verdadero o falso, respectivamente. El lenguaje máquina del MIPS32 dispone de una instrucción que justamente realiza una comparación del tipo menor que entre dos registros y carga un 1 o un 0 en un tercer registro dependiendo del resultado de la comparación (verdadero o falso, respectivamente). ´ Esta es la instrucción slt (set if less than) y presenta la siguiente sintaxis: slt rd, rs, rt. De hecho, la instrucción slt es la única instrucción de comparación que proporciona el procesador MIPS32. Sin embargo, y al igual que ocurría con las instrucciones de salto condicional, el ensamblador proporciona una serie de pseudo-instrucciones que facilitan la programación en ensamblador. ´ Estas son: sge (poner a 1 si mayor o igual), sgt (poner a 1 si mayor), `` sle `` (poner a 1 si menor o igual), sne (poner a 1 si distinto), seq (poner a 1 si igual).

Actividades (2 puntos)

Describe utilizando la nomenclatura introducida en esta sección el significado de las siguientes pseudo-instrucciones (utiliza == como operador de igualdad y < como operador de desigualdad):

  1. sge rd, rs, rt
  2. sne rd, rs, rt
  3. seq rd, rs, rt
  4. ¿Qué significa en inglés el nemónico bge? ¿Y blt?

Trabajo en el Laboratorio (8 puntos)

Evaluación de condiciones simples

Introduce y ejecuta el siguiente código que compara dos variables, dato1 y dato2 (con los valores 30 y 40 en el ejemplo) y almacena en la variable res el resultado de dicha comparación.

  comp-slt.s
1   .data # zona de datos
2 dato1: .word 30  
3 dato2: .word 40  
4 res: .space 1  
5      
6   .text # zona de instrucciones
7 main: lw $t0, dato1 # Carga M[dato1] en $t0
8   lw $t1, dato2 # Carga M[dato2] en $t1
9   slt $t2, $t0, $t1 # $t2 <- (t0<t1)?1:0
10   sb $t2, res($0) # Almacena $t2 en M[res]

Actividades (2 puntos)

  1. Carga y ejecuta el programa anterior. ¿Qué valor se almacena en la posición de memoria res?
  2. Inicializa las posiciones de memoria dato1 y dato2 con los valores 50 y 20, respectivamente y ejecuta de nuevo el programa. ¿Qué valor se carga ahora en la posición de memoria res?
  3. ¿Qué condición se ha evaluado?
  4. Modifica el código anterior para que evalúe la siguiente condición: res <- (dato1>=dato2). Utiliza la pseudo-instrucción que implementa dicha comparación.
  5. Resuelve el ejercicio anterior pero esta vez utilizando la instrucción sle.

Evaluación de condiciones compuestas - 1

Una condición compuesta está formada por varias comparaciones y operadores lógicos. Por ejemplo, para averiguar si una persona está entre los 20 y los 40 años se podría evaluar la siguiente condición compuesta2. Dicha condición compuesta está formada por dos comparaciones unidas por el operador lógico y.

  comp-cmp.s
1   .data # zona de datos
2 dato1: .word 30  
3 dato2: .word 50  
4 res: .space 1  
5      
6   .text # zona de instrucciones
7 main: lw $t8, dato1($0) # Carga M[dato1] en $t8
8   lw $t9, dato2($0) # Carga M[dato2] en $t9
9   and $t0, $t0, $0  
10   and $t1, $t1, $0  
11   beq $t8, $0, igual # Salta a igual si $t8=0
12   ori $t0, $0, 1  
13 igual: beq $t9, $0,fineval # Salta a fineval si $t9=0
14   ori $t1, $0, 1  
15 fineval: and $t2, $t0, $t1  
16   sb $t2, res($0)  

Actividades (2 puntos)

  1. Carga el programa anterior en el simulador y ejecútalo. ¿Qué valor se almacena en la posición de memoria referenciada por la etiqueta res?

11. Para cada par de valores de los mostrados en la siguiente tabla realiza las siguientes operaciones. (i) Modifica los valores almacenados en las posiciones de memoria referenciadas por las etiquetas dato1 y dato2 con los valores indicados. (ii) Ejecuta el programa de nuevo (modificando la dirección de comienzo en caso necesario). (iii) Anota el valor almacenado en la posiciónn de memoria referenciada por la etiqueta res.

dato1 dato2 res
10 20  
20 0  
0 0  

Analiza ahora cómo funciona el código contestando a las siguientes preguntas.

  1. ¿Para qué sirve la instrucción and $t0, $t0, $0? ¿Y la instrucción and $t1, $t1, $0?
  2. ¿Qué es lo que hace la instrucción ori $t0, $0, 1? ¿Qué condición debe cumplirse para que se ejecute?
  3. ¿Qué es lo que hace la instrucción ori $t1, $0, 1? ¿Qué condición debe cumplirse para que se ejecute?
  4. ¿Qué es lo que hace la instrucción and $t2, $t0, $t1?
  5. A la vista de las respuestas a las 4 preguntas anteriores, ¿qué condición compuesta está evalúando el programa anterior?
  6. Por último, modifica el código anterior para que la condición evaluada sea:
res <- (dato1!=0) and (dato1!=dato2).

Evaluación de condiciones compuestas - 2

El siguiente programa es ligeramente distinto al anterior:

  comp-cmp2.s
1   .data # zona de datos
2 dato1: .word 30  
3 dato2: .word -50  
4 res: .space 1  
5      
6   .text # zona de instrucciones
7 main: lw $t8, dato1($0) # Carga M[dato1] en $t8
8   lw $t9, dato2($0) # Carga M[dato2] en $t9
9   and $t0, $t0, $0  
10   and $t1, $t1, $0  
11   beq $t8, $0, igual # Salta a igual si $t8=0
12   ori $t0, $0, 1  
13 igual: slt $t1, $t9, $t8  
15 fineval: and $t0, $t0, $t1  
16   sb $t2, res($0)  

Actividades (2 puntos)

Comenta adecuadamente el código para entender qué es lo que hace.

  1. ¿Cuál es la condición compuesta evaluada?
  2. Inicializa la memoria y registros del simulador, carga el código y ejecútalo. ¿Qué valor se almacena en la posición de memoria res?
  3. Sobrescribe las posiciones de memoria dato1 y dato2 con los valores 10 y 20 y ejecuta de nuevo el código. ¿Qué valor se almacena ahora en la posición de memoria res?
  4. Sobrescribe las posiciones de memoria dato1 y dato2 con los valores 0 y -20 y vuelve a ejecutarlo. ¿Qué valor se ha almacenado ahora en la posición de memoria res?

Evaluación de condiciones compuestas - 3

Por último, el siguiente ejemplo es ligeramente distinto a los anteriores.

  comp-cmp3.s
1   .data # zona de datos
2 dato1: .word 30  
3 dato2: .word -20  
4 res: .space 1  
5      
6   .text # zona de instrucciones
7 main: lw $t8, dato1($0) # Carga M[dato1] en $t8
8   lw $t9, dato2($0) # Carga M[dato2] en $t9
9   and $t0, $t0, $0  
10   and $t1, $t1, $0  
11   alt $t0, $t8, $t8  
12   bne $t9, $t8, $t9  
13   ori $t1,$0,$1  
15 fineval: or $t0, $t0, $t1  
16   sb $t2, res($0)  

Actividades (2 puntos)

Comenta adecuadamente el código para entender qué es lo que hace.

  1. ¿Cuál es la condición compuesta evaluada?
  2. Inicializa la memoria y registros del simulador, carga el código y ejecútalo. ¿Qué valor se almacena en la posición de memoria res?
  3. Sobrescribe las posiciones de memoria dato1 y dato2 con los valores -20 y 10 y ejecuta de nuevo el código. ¿Qué valor se almacena ahora en la posición de memoria res?
  4. Sobrescribe las posiciones de memoria dato1 y dato2 con los valores 10 y 0 y vuelve a ejecutarlo. ¿Qué valor se ha almacenado ahora en la posición de memoria res?
  5. Sobrescribe las posiciones de memoria dato1 y dato2 con los valores 20 y 10 y vuelve a ejecutarlo. ¿Qué valor se ha almacenado ahora en la posición de memoria res?
  6. Por último, modifica el código anterior para que la condición evaluada sea
res<-``dato1<=dato2`` or ``dato1<=0``.