Examen Final Enero 2013 (2013)

Examen Español
Universidad Universidad Politécnica de Cataluña (UPC)
Grado Ingeniería de Sistemas de Telecomunicación - 1º curso
Asignatura Fonamentos de Ordenadores
Año del apunte 2013
Páginas 14
Fecha de subida 16/09/2014
Descargas 0
Subido por

Vista previa del texto

Fonaments d’Ordinadors 18 de enero de 2013 Departament d’Arquitectura de Computadors Notas provisionales: 22/01/2013 a partir de las 16:00 Alegaciones: 24/01/2013 hasta las 20:00 Notas definitivas: 28/01/2013 a partir de las 18:00 Profesores: Gil M., Guerrero M., Heredero A., Jiménez M., Llorente S., Macias M., Monreal T., Pérez J. L., Otero B., Valverde X.
• • • • Duración del examen: 3h.
Contestar los problemas 1, 2 y 3 en hojas de examen separadas (hojas cuadriculadas).
Se puede consultar únicamente la documentación entregada en el examen.
No se puede utilizar ningún dispositivo electrónico durante la realización del examen.
Problema 1 (2.0 puntos, 50 minutos) a) (0.75 ptos) Se quiere diseñar un programa en C que indique la cantidad de caracteres que hay que recorrer de un texto hasta encontrar las N primeras apariciones de un carácter determinado, tanto en mayúsculas como en minúsculas.
Por ejemplo, si el texto es: “The Little Prince asks the flier that will draw a lamb  to take to their world.” y buscamos las 3 primeras apariciones del carácter ‘T’, el programa indicará: Se han recorrido 8 caracteres del texto y se han encontrado  las   3   primeras   apariciones   del   carácter‘T’:   1   en   mayúsculas   y   2   en  minúsculas.
Para realizar la implementación del programa se debe tener en cuenta que: • El carácter a buscar y el número de apariciones se piden al usuario por teclado.
• El carácter que se pide al usuario SIEMPRE estará en mayúsculas. Sin embargo, en el texto se buscarán apariciones en mayúsculas y minúsculas.
• El texto finaliza con el carácter ‘\0’.
• Sea CAR el carácter que buscamos, N (N>0) el número de apariciones que buscamos, X el número de apariciones que realmente encontramos en el texto, MAY el número de apariciones en mayúsculas, MIN el número de apariciones en minúsculas y NUM el número de caracteres del texto que se han recorrido para encontrar las N primeras apariciones, entonces: En caso de que no se encuentre el carácter CAR en el texto (X=0), el programa mostrará por pantalla el siguiente mensaje: No hay apariciones del carácter CAR en el texto.
En caso de que se encuentre al menos una vez el carácter CAR, pero no se encuentran las N apariciones (0<X<N), el programa mostrará por pantalla el siguiente mensaje: Se ha  recorrido todo el texto y sólo se han encontrado  X  apariciones del carácter  CAR:  MAY en mayúsculas y MIN en minúsculas.
En cualquier otro caso (X=N), el programa mostrará por pantalla el siguiente mensaje: Se  han   recorrido   NUM   caracteres   del   texto   y   se   han   encontrado   las  N  primeras  apariciones del carácter CAR: MAY en mayúsculas y MIN en minúsculas.
• Suponga que no hay error en los datos que introduce el usuario por teclado. Es decir, el carácter CAR  siempre estará en mayúsculas y N  será un valor numérico entero positivo mayor que 0.
• No se puede usar ninguna función de la librería string.h.
A continuación mostramos el esqueleto del programa. Declare las variables adicionales que necesite para realizar la implementación y complete el código del programa que falta.
#define MAXVECT 1000 main(){ char texto[MAXVECT]= "The Little Prince asks the flier that will draw a lamb to                            take to their world. After becoming a friend of the aviator,                            tells how lonely and melancholy was his life until the                            arrival of the Flower, a beautiful flower that loves the                            Prince but who finds it difficult to express with                            sincerity.";      int N;      char car; /* Declarar las variables necesarias */ printf ("Introduce el caracter a buscar (EN MAYUSCULA) y el número de apariciones, separados por un espacio: "); scanf ("%c %d%*c", &car, &N); } /* COMPLETAR */ 1 Ejemplo de ejecución (en negrita se muestra la entrada de datos desde teclado): Introduce el carácter a buscar (EN MAYUSCULA) y el número de apariciones,  separados por un espacio: A 10 Se han recorrido 114 caracteres del texto y se han encontrado las 10 primeras  apariciones del carácter ‘A’: 1 en mayúsculas y 9 en minúsculas.   b) (1.25 ptos) Modifique el programa anterior para que ahora encuentre las N primeras apariciones de una cadena de caracteres (en lugar de encontrar un carácter determinado).
Ahora se debe buscar en el texto la cadena exactamente igual que la introducida por el usuario, distinguiendo entre mayúsculas y minúsculas. Es decir, la cadena “the” y “The” no son iguales.
Para realizar la implementación del programa se debe tener en cuenta que: • La cadena a buscar y el número de apariciones se piden al usuario por teclado.
• El texto finaliza con el carácter ‘\0’ y la cadena que introduce el usuario finaliza con el carácter ‘\n’.
• Sea CAD la cadena que buscamos, N (N>0) el número de apariciones que buscamos, X el número de apariciones que realmente encontramos en el texto y NUM el número de caracteres del texto que se han recorrido para encontrar las N  primeras apariciones, entonces: En caso de que no se encuentre la cadena CAD en el texto (X=0), el programa mostrará por pantalla el siguiente mensaje: No hay apariciones de la cadena CAD.  En caso de que se encuentre al menos una vez la cadena CAD, pero no se encuentran las N apariciones (0<X<N), el programa mostrará por pantalla el siguiente mensaje: Se ha  recorrido todo el texto y sólo se han encontrado X apariciones de la cadena CAD.  En cualquier otro caso (X=N), el programa mostrará por pantalla el siguiente mensaje: Se   han   recorrido   NUM   caracteres   del   texto   y   se   han   encontrado   las  N  primeras  apariciones de la cadena CAD.
• Suponga que no hay error en los datos que introduce el usuario por teclado. Es decir, N  siempre será un valor entero positivo mayor que 0 y la cadena CAD siempre acabará con el carácter ‘\n’ y tendrá menos de MAXCAR caracteres.
• No se puede usar ninguna función de la librería string.h, ni tampoco el especificador de formato %s.
A continuación mostramos el esqueleto del programa. Declare las variables adicionales que necesite para realizar la implementación y complete el código del programa que falta.
#define MAXVECT 1000 #define MAXCAR 10 main(){      char texto[MAXVECT]= "The Little Prince asks the flier that will draw a lamb to                           take to their world. After becoming a friend of the aviator,                           tells how lonely and melancholy was his life until the                           arrival of the Flower, a beautiful flower that loves the                           Prince but who finds it difficult to express with                           sincerity.";      int N;      char cad[MAXCAR]; /* Declarar las variables necesarias */      printf ("Introduce el numero de apariciones: ");      scanf ("%d%*c", &N);   printf("Introduce la cadena de caracteres a buscar finalizada en '\n': "); /* COMPLETAR */ } Ejemplo de ejecución 1 (en negrita se muestra la entrada de datos desde teclado): Introduce el numero de apariciones: 5 Introduce la cadena de caracteres a buscar finalizada en '\n': to Se ha recorrido todo el texto y sólo se han encontrado 4 apariciones de la cadena “to”.
Ejemplo de ejecución 2 (en negrita se muestra la entrada de datos desde teclado): Introduce el numero de apariciones: 2 Introduce la cadena de caracteres a buscar finalizada en '\n': he Se   han   recorrido   26   caracteres   del   texto   y   se   han   encontrado   las  2   primeras  apariciones de la cadena “he”.
2 Problema 2 (4.0 puntos, 70 minutos) Se quiere implementar un programa que calcule los precios rebajados de un conjunto de artículos que se quieren poner a la venta en las segundas rebajas de la tienda GRAN ALMACEN. Para ello, se dispone de las siguientes estructuras de datos: #define MAX_CHAR 50 #define MAX_ART 200 typedef struct{         int id; /* Id del artículo */         char nombre[MAX_CHAR]; /* Nombre del artículo */         float precio; /* Precio */         int descuento; /* Descuento a aplicar */         float precio_rebajado;   /* Precio después de aplicar el descuento */ } tarticulo; typedef struct{         int num_articulos;         tarticulo larts[MAX_ART]; } tlista_articulos; /* Número total de artículos */ /* Lista de artículos, no está ordenada */   main(){   tlista_articulos rebajas = {5, {{1,"Camiseta roja ", 15, 25, ­1},                                  {2, "Guantes de lana", 25, 30, ­1},                                   {3, "Gorro de lana", 40, 25, ­1},                                   {4, "Botas", 25, 45, ­1},                                   {5, "Abrigo", 15, 40, ­1}}}; /* COMPLETAR */ } El tipo de dato tarticulo permite almacenar la información de un artículo (identificador, nombre, precio original, porcentaje de descuento y precio rebajado).
Por ejemplo: {1,"Camiseta roja ", 15, 25, ­1}. El valor ­1 indica que todavía no se ha calculado el precio rebajado del articulo Camiseta roja. El valor 25 significa que se debe aplicar un descuento del 25%.
El tipo de dato tlista_articulos permite almacenar la lista de artículos que se quieren rebajar. El campo num_articulos indica cuántos artículos hay almacenados en el campo larts. La lista no está ordenada.
Se quiere implementar un programa que, dada una lista de artículos, calcule los precios rebajados de cada articulo y muestre por pantalla la lista de artículos ordenada de menor a mayor descuento. Además, el programa también mostrará por pantalla los datos de todos los artículos que tengan el menor descuento.
Ejemplo: Después de la ejecución del programa y suponiendo la inicialización anterior, la variable rebajas, debe almacenar: rebajas = {5, {{1,"Camiseta  roja ", 15, 25, 11.25}, {2, "Guantes de lana",  25, 30, 17.5}, {3, "Gorro de lana", 40, 25, 30}, {4, "Botas", 25, 45, 13.75},  {5, "Abrigo", 15, 40, 9}}};  y por pantalla veremos: Lista ordenada de articulos:  Identificador: 1 Nombre: Camiseta roja  Precio: 15.00 Descuento aplicado: 25% Precio rebajado: 11.25 Identificador: 3 Nombre: Gorro de lana Precio: 40.00 Descuento aplicado: 25% Precio rebajado: 30.00 Identificador: 2 Nombre: Guantes de lana Precio: 25.00 Descuento aplicado: 30% 3 Precio rebajado: 17.50 Identificador: 5 Nombre: Abrigo Precio: 15.00 Descuento aplicado: 40% Precio rebajado: 9.00 Identificador: 4 Nombre: Botas Precio: 25.00 Descuento aplicado: 45% Precio rebajado: 13.75 Los articulos con menor descuento son:  Identificador: 1 Nombre: Camiseta roja  Precio: 15.00 Descuento aplicado: 25% Precio rebajado: 11.25 Identificador: 3 Nombre: Gorro de lana Precio: 40.00 Descuento aplicado: 25% Precio rebajado: 30.00 Se pide implementar las siguientes funciones y el programa principal: a) (0.5 pto) void mostrar_articulo(tarticulo a)  Esta función muestra por pantalla los datos del artículo almacenado en el parámetro a. Si el precio rebajado es ­1, entonces sólo muestra el identificador, el nombre y el precio original.
Si el precio rebajado está calculado, entonces también se muestra el descuento y el precio rebajado del artículo.
Para implementar esta función debéis usar la siguiente función: void mostrar_cadena (char cad[MAX_CHAR])  Esta función muestra por pantalla la cadena cad que se le pasa como parámetro.
NOTA: Suponer que la función mostrar_cadena ya está hecha. No hay que implementarla.
b) (1.0 pto) void   mostrar_lista_articulos_ordenada_por_descuento(tlista_articulos   la)  Esta función muestra por pantalla los artículos de la lista almacenada en el parámetro la  ordenados de menor a mayor según el porcentaje de descuento a aplicar. Se debe comprobar que la lista tiene artículos. En caso negativo, debe mostrarse por pantalla el siguiente mensaje: “No hay artículos”.
Para implementar esta función debéis utilizar la función: void mostrar_articulo(tarticulo a).
c) (0.5 ptos) void calcular_precio_rebajado(tlista_articulos *la) Esta función calcula los precios rebajados de todos los artículos de la lista apuntada por el parámetro la. Si el precio rebajado de un artículo ya estaba calculado, no lo vuelve a calcular. Se debe comprobar que la lista tiene artículos. En caso negativo, debe mostrarse por pantalla el siguiente mensaje: “No hay artículos”.
d) (1.0 pto) void buscar_menos_rebajados(tlista_articulos la) Muestra por pantalla el artículo o los artículos (en el caso de haber varios) con el menor descuento (menos rebajado) de la lista almacenada en el parámetro la. Se debe comprobar que la lista tiene artículos. En caso negativo, debe mostrarse por pantalla el siguiente mensaje: “No hay artículos”.
Para implementar esta función debéis utilizar la función: void mostrar_articulo(tarticulo a).
NOTA: Suponga que el precio rebajado de todos los artículos ya ha sido calculado.
e) (1.0 pto) Escriba el programa principal para que, dada una lista de artículos, calcule los precios rebajados de todos los articulos y muestre por pantalla la lista de artículos ordenada de menor a mayor descuento. Además, el programa también mostrará por pantalla los datos de todos los artículos que tengan el menor descuento.
NOTA: Utilice las funciones anteriores que sean necesarias.
4 Problema 3 (4.0 puntos, 60 minutos) Tenemos el siguiente código en C que calcula el máximo común divisor de una serie de valores enteros por el método de Euclides. Queremos traducir completamente este código en C a código ensamblador IA32: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 #define NUM 5 int modulo (int dividendo, int divisor) { while (dividendo-divisor>=0) dividendo=dividendo-divisor; return (dividendo); } int max_comun_divisor ( int a, int b) { int r; while (b!=0) { r=modulo(a,b); a=b; b=r; } return (a); } main() { short vec[NUM]; int mcd; int i; /* inicializacion de vec[0..NUM-1] */ mcd=vec[0]; for (i=1; i<NUM; i++) { mcd=max_comun_divisor(mcd, vec[i]); } } Responda a las siguientes preguntas: a) (0.15 ptos) Traduzca a ensamblador IA32 las líneas del código 1, 23 y 24 (definición de constantes y declaración de variables sin inicializar).
b) (0.25 ptos) Traduzca a ensamblador IA32 la línea 29 del código.
c) (0.3 ptos) Traduzca a ensamblador IA32 las líneas 30, 31 y 33 (sin la llamada a la función max_comun_divisor), asumiendo que la variable i se almacena en %esi.
d) (0.5 ptos) Traduzca a ensamblador IA32 la línea 32 del código, asumiendo que el valor de la variable i está almacenado en el registro %esi.
e) (0.3 ptos) Dibuje el estado de la pila (bloque de activación) durante la ejecución de las subrutinas modulo y max_comun_divisor, indicando claramente donde apuntan los registros %esp y %ebp. No se puede suponer que las variables locales están en registros.
Indique claramente los desplazamientos respecto al %ebp de los parámetros y variables locales.
f) (0.5 ptos) Traduzca a ensamblador IA32 la línea 15 del código.
g) (0.3 ptos) Traduzca a ensamblador IA32 las líneas 16 y 17 del código.
h) (0.6 ptos) Complete el siguiente código que corresponde a la traducción en ensamblador IA32 de la función modulo (líneas 3-8): modulo: pushl %ebp movl %esp, %ebp #COMPLETAR popl %ebp ret 5 Ahora vamos a modificar las funciones modulo y max_comun_divisor para que devuelvan el resultado a través de un parámetro por referencia en vez de devolverlo a través del return. Las líneas de código que modificaremos serán las siguientes: Línea 3 Sustituir este código: int modulo(int dividendo,int divisor) por este otro: void modulo(int dividendo, int divisor, int *resto) 10 int max_comun_divisor( int a,int b) void max_comun_divisor(int a, int b, int *result) 15 r=modulo(a,b); modulo(a, b, &r); 32 mcd=max_comun_divisor(mcd,vec[i]); max_comun_divisor( mcd, vec[i], &mcd); 7 return (dividendo); *resto = dividendo; 19 return (a); *result = a; i) (0.2 ptos) Indique como quedarán ahora los bloques de activación de las subrutinas modulo y max_comun_divisor. Indique claramente en qué difieren respecto a los bloques de activación del apartado e).
j) (0.3 ptos) Traduzca a ensamblador IA32 la nueva línea 32 del código.
k) (0.3 ptos) Traduzca a ensamblador IA32 la nueva línea 15 del código.
l) (0.3 ptos) Traduzca a ensamblador IA32 la nueva línea 7 del código.
6 Documentación para el problema 3 Operaciones involucradas en el uso de subrutinas: SUBR1 (Subrutina que llama) SUBR2 (Subrutina llamada) 1 4 5 6 2 3 12 13 14 Salvar registros (%eax, %ecx, %edx) Paso de parámetros Llamada a SUBR2 Recoger resultado Eliminar parámetros Restaurar registros (%edx, %ecx, %eax) Establecer enlace dinámico Reservar espacio para variables locales Salvar registros (%ebx, %esi, %edi) # Código de SUB2 7 8 Devolver resultado Restaurar registros (%edi, %esi, %ebx) Liberar espacio de variables locales Deshacer enlace dinámico Retorno 9 10 11 NOTA: La numeración indica el orden cronológico en el que se ejecutan las operaciones.
Instrucciones básicas de IA32: /* Copiar contenidos: op2 = op1 */ movl op1, op2 movw op1, op2 movb op1, op2 /* op2, op1 de 4 bytes */ /* op2, op1 de 2 bytes */ /* op2, op1 de 1 byte */ /* Suma: op2 = op2 + op1 */ addl op1, op2 addw op1, op2 addb op1, op2 /* op2, op1 de 4 bytes */ /* op2, op1 de 2 bytes */ /* op2, op1 de 1 byte */ /* Resta: op2 = op2 - op1 */ subl op1, op2 subw op1, op2 subb op1, op2 /* op2, op1 de 4 bytes */ /* op2, op1 de 2 bytes */ /* op2, op1 de 1 byte */ /* Incremento: op1 = op1 + 1 inc[b|w|l] dec[b|w|l] /* Producto: op2 = op2 * op1 imull op1, op2 imull op1, op2, op3 imulw op1, op2 imulw op1, op2, op3 Decremento: op1 = op1 - 1 */ /* op1 = op1 + 1 con op1 de 1, 2 ó 4 bytes */ /* op1 = op1 -1 con op1 de 1, 2 ó 4 bytes */ ó op3 = op2 * op1*/ /* op2, op1 de 4 bytes.op2 es registro */ /* /* /* /* /* op3, op2, op1 de 4 bytes, op1 es inmediato, op2 es memoria o registro y op3 es registro op2, op1 de 2 bytes, op2 es registro op3, op2, op1 de 2 bytes, op1 es inmediato, op2 es memoria o registro y op3 es registro */ */ */ */ /* Salto incondicional */ jmp etiqueta /* salto a etiqueta */ /* Comparación: op2 - op1, sólo modifica registro de flags */ cmpl op1, op2 cmpw op1, op2 cmpb op1, op2 /* op2, op1 de 4 bytes */ /* op2, op1 de 2 bytes */ /* op2, op1 de 1 byte */ /* Salto condicional según valores del registro de flags */ je jne jg jge jl jle etiqueta etiqueta etiqueta etiqueta etiqueta etiqueta /* /* /* /* /* /* salto salto salto salto salto salto a a a a a a etiqueta etiqueta etiqueta etiqueta etiqueta etiqueta si si si si si si op1 op1 op2 op2 op2 op2 == op2 != op2 > op1 >= op1 < op1 <= op1 */ */ */ */ */ */ /* Conversión de tipo: op2 = ExtSigno(op1) */ movsbl movsbw movswl op1, op2 op1, op2 op1, op2 /* op2 de 4 bytes, op1 de 1 byte. op2 es registro */ /* op2 de 2 bytes, op1 de 1 byte. op2 es registro */ /* op2 de 4 bytes, op1 de 2 byte. op2 es registro */ /* Gestión de subrutinas */ call etiqueta ret /* Salto a etiqueta y guarda en pila la dirección de retorno */ /* Saca de la pila la dirección de retorno y ejecuta la instrucción que se encuentra en la dirección de retorno */ /* Instrucciones para el manejo de la pila */ push[w|l] op1 pop[w|l] op1 /* Copia el operando op1 en la cima de la pila. op1 de 2 ó 4 bytes */ /* Copia en el operando op1 lo que se encuentra en la cima de la pila op1 de 2 ó 4 bytes */ 7 Soluciones Problema 1 (2.0 puntos, 50 minutos) a) (0.75 ptos). La respuesta que se pide aparece en negrita.
#include <stdio.h> #define MAXVECT 1000 main() {      char texto[MAXVECT]= "The Little Prince asks the flier that will draw a lamb to                             take to their world. After becoming a friend of the                             aviator, tells how lonely and melancholy was his life until                             the arrival of the Flower, a beautiful flower that loves                             the Prince but who finds it difficult to express with                             sincerity.";      int N, i, may=0, min=0;      char car;      printf ("Introduce el caracter a buscar (EN MAYUSCULA) y el numero de                        apariciones, separados por un espacio: ");      scanf ("%c %d%*c", &car, &N);      i=0;      while (texto[i] != '\0' && may+min<N)       {           if (texto[i] == car) may++;           else if (texto[i] == car + ('a'­'A')) min++;           i++;      }             if (may+min==0)           printf("No hay apariciones del caracter '%c' en el texto.\n", car);      else if (may+min < N)           printf("Se ha recorrido todo el texto y solo se han encontrado %d  apariciones del caracter '%c': %d en mayusculas y %d en  minusculas\n", may+min,car, may, min);      else           printf("Se han recorrido %d caracteres del texto y se han encontrado las %d                    primeras apariciones del caracter '%c': %d en mayusculas y %d en                    minusculas\n", i, N, car, may, min); } b) (1.25 ptos). La respuesta que se pide aparece en negrita.
#include <stdio.h> #define MAXVECT 1000 #define MAXCAR 10 main() {      char texto[MAXVECT]= "The Little Prince asks the flier that will draw a lamb to                             take to their world. After becoming a friend of the                             aviator, tells how lonely and melancholy was his life until                             the arrival of the Flower, a beautiful flower that loves                             the Prince but who finds it difficult to express with                             sincerity.";      int N, i, j, cont=0;      char cad[MAXCAR];      printf ("Introduce el numero de apariciones: ");      scanf ("%d%*c", &N);      printf ("Introduce la cadena de caracteres a buscar finalizada en '\\n': ");      i=0;      scanf("%c", &cad[i]);      while (cad[i]!='\n')      {          i++;          scanf("%c", &cad[i]);      }      cad[i]='\0';      i=0;      while (texto[i] != '\0' && cont<N)       {           j=0;           while (cad[j]!='\0' && texto[i+j]!='\0' && texto[i+j]==cad[j]) j++; 8           if (cad[j] == '\0') cont++;           i++;      }             if (cont==0)         printf("No hay apariciones de la cadena \"");      else if (cont < N)           printf("Se ha recorrido todo el texto y solo se han encontrado %d                    apariciones de la cadena \"", cont);      else          printf("Se han recorrido %d caracteres del texto y se han encontrado las %d                   primeras apariciones de la cadena \"", i+j­1, N);      for (i=0; cad[i]!='\0'; i++) printf ("%c", cad[i]);      printf("\".\n");  } 9 Problema 2 (4.0 puntos, 70 minutos) #include <stdio.h> #define MAX_CHAR 50 #define MAX_ART 200 typedef struct {         int id;                 /* Id del artículo */         char nombre[MAX_CHAR];  /* Nombre del artículo */         float precio;           /* Precio */         int descuento;          /* Descuento a aplicar */         float precio_rebajado;  /* Precio después de aplicar el descuento */ } tarticulo; typedef struct {         int num_articulos;        /* Número total de artículos */         tarticulo larts[MAX_ART]; /* Lista de artículos, no está ordenada */ } tlista_articulos; void mostrar_cadena(char cad[MAX_CHAR]); void mostrar_articulo(tarticulo a); void mostrar_lista_articulos_ordenada_por_descuento(tlista_articulos la); void calcular_precio_rebajado(tlista_articulos *la); void buscar_menos_rebajados(tlista_articulos la); /* e) (1.0 pto) */ main() { tlista_articulos rebajas = {5, {{1,"Camiseta roja ", 15, 25, ­1},                                  {2, "Guantes de lana", 25, 30, ­1},                                   {3, "Gorro de lana", 40, 25, ­1},                                   {4, "Botas", 25, 45, ­1},                                   {5, "Abrigo", 15, 40, ­1}}}; calcular_precio_rebajado (&rebajas); mostrar_lista_articulos_ordenada_por_descuento (rebajas); buscar_menos_rebajados(rebajas); } void mostrar_cadena(char cad[MAX_CHAR]) { int i = 0; while (i < MAX_CHAR && cad[i] != '\0' ) printf ("%c", cad[i++]); } /* a) (0.5 ptos) */ void mostrar_articulo(tarticulo a) {         printf ("\nIdentificador: %d\nNombre: ", a.id);         mostrar_cadena (a.nombre);         printf ("\nPrecio: %.2f\n", a.precio);         if (a.precio_rebajado > ­1)         {                 printf ("Descuento aplicado: %d%%\n", a.descuento);                 printf ("Precio rebajado: %.2f\n", a.precio_rebajado);         } } /* b) (1.0 pto) */ void mostrar_lista_articulos_ordenada_por_descuento(tlista_articulos la) {     int i = 0, j;     tarticulo aux;                  if (la.num_articulos == 0)        printf ("No hay articulos\n");     else     {             10        for (i=0; i < la.num_articulos ­ 1; i++)                        {            for (j=i+1; j < la.num_articulos; j++)            {               if (la.larts[i].descuento > la.larts[j].descuento)               {                 aux = la.larts [i];                 la.larts [i] = la.larts [j];                 la.larts [j] = aux;               }            }                        }             printf ("\nLista ordenada de articulos: \n");        for (i = 0; i < la.num_articulos; i++)            mostrar_articulo (la.larts[i]);     } } /* c) (0.5 ptos) */ void calcular_precio_rebajado (tlista_articulos *la) {         int i = 0;         if (la­>num_articulos == 0)                 printf ("No hay articulos\n");         else         {             for (i = 0; i < la­>num_articulos; i++) if (la­>larts[i].precio_rebajado < 0) la­>larts[i].precio_rebajado = la­>larts[i].precio ­                                 la­>larts[i].precio *                                 la­>larts[i].descuento/100;   } } /* d) (1.0 pto) */ void buscar_menos_rebajados (tlista_articulos la) {         int i = 0;           int menor_descuento;                  if (la.num_articulos == 0)             printf ("No hay articulos\n");         else         { menor_descuento = la.larts[0].descuento; for (i = 1; i < la.num_articulos; i++) if (menor_descuento > la.larts[i].descuento) menor_descuento = la.larts[i].descuento; printf ("\nLos articulos con menor descuento son: \n"); for (i = 0; i < la.num_articulos; i++) if (la.larts[i].descuento == menor_descuento) mostrar_articulo (la.larts[i]);         }                 } 11 Problema 3 (4.0 puntos, 60 minutos) Responda a las siguientes preguntas en esta misma hoja: a) (0.15 ptos) Traduzca a ensamblador IA32 la línea del código 1, 23 y 24 (definición de constantes y declaración de variables sin inicializar).
NUM=5 .comm vec, NUM*2, 2 .comm mcd, 4, 4 b) (0.25 ptos) Traduzca a ensamblador IA32 la línea 29 del código.
movswl vec, %eax    movl %eax, mcd      # mcd=vec[0]; c) (0.3 ptos) Traduzca a ensamblador IA32 las líneas 30, 31 y 33 (sin la llamada a la función max_comun_divisor), asumiendo que la variable i se almacena en el registro %esi.
 movl $1, %esi      for:   cmpl $NUM, %esi            jge endfor        . . .               # i=1; # (i<NUM)        incl %esi                  jmp for endfor: # i++ # línea 32 d) (0.5 ptos) Traduzca a ensamblador IA32 la línea 32 del código, asumiendo que el valor de la variable i está almacenado en el registro %esi.
movswl vec(,%esi,2), %ebx   pushl %ebx          pushl mcd           call max_comun_divisor movl %eax, mcd            addl $8, %esp e) (0.3 ptos) Dibuje el subrutinas modulo y registros %esp y %ebp.
Indique claramente los locales.
# mcd=max_comun_divisor (mcd, vec[i]) estado de la pila (bloque de activación) durante la ejecución de las max_comun_divisor, indicando claramente donde apuntan los No podéis suponer que las variables locales están en registros.
desplazamientos respecto al %ebp de los parámetros y variables      modulo registros %ebp anterior @retorno/%eip dividendo divisor registros  # parámetro real vec[i] # parámetro real mcd ←%esp ←%ebp ←%ebp+4 ←%ebp+8 ←%ebp+12 max_comun_divisor registros ←%esp r ←%ebp­4 %ebp anterior ←%ebp @retorno/%eip ←%ebp+4 a ←%ebp+8 b ←%ebp+12 registros f) (0.5 ptos) Traduzca a ensamblador IA32 la línea 15 del código.
pushl 12(%ebp)       pushl 8(%ebp)        call modulo          movl %eax, ­4(%ebp)  addl $8, %esp # parámetro real b # parámetro real a # r=modulo (a,b); g) (0.3 ptos) Traduzca a ensamblador IA32 las líneas 16 y 17 del código.
movl 12(%ebp), %ebx  movl %ebx, 8(%ebp)   movl ­4(%ebp), %ebx movl %ebx, 12(%ebp)  # a=b # b=r h) (0.6 ptos) Complete el siguiente código que corresponde a la traducción en ensamblador IA32 de la función modulo (líneas 3-8): 12 modulo:         pushl %ebp         movl %esp, %ebp         # COMPLETAR         pushl %ebx         movl 12(%ebp), %ecx   # %ecx=divisor         movl 8(%ebp), %ebx    # %ebx=dividendo while:  movl %ebx, %edx         subl %ecx, %edx       # %edx = dividendo­divisor         cmpl $0, %edx         # (dividendo­divisor >=0)         jl finwhile         movl  %edx, %ebx      # dividendo = dividendo­divisor         jmp while finwhile:         movl %ebx, %eax       # return (dividendo)         popl %ebx         popl %ebp         ret Ahora vamos a modificar las funciones modulo y max_comun_divisor para que devuelvan el resultado a través de un parámetro por referencia en vez de devolverlo a través del return. Las líneas de código que modificaremos serán las siguientes: Línea Sustituir este código: por este otro: 3 int modulo(int dividendo,int divisor) void modulo(int dividendo,int divisor, int *resto) 10 int max_comun_divisor(int a,int b) void max_comun_divisor ( int a, int b, int *result) 15 r=modulo(a,b); modulo(a,b, &r); 32 mcd=max_comun_divisor(mcd,vec[i]); max_comun_divisor(mcd, vec[i], &mcd); 7 return (dividendo); *resto = dividendo; 19 return (a); *result = a; i) (0.2 ptos) Indique como quedarán ahora los bloques de activación de las subrutinas modulo y max_comun_divisor. Indique claramente en qué difieren respecto a los bloques de activación del apartado e).
modulo registros %ebp anterior @retorno/%eip dividendo divisor resto (int *) registros  ←%esp ←%ebp ←%ebp+4 ←%ebp+8 ←%ebp+12 ←%ebp+16 max_comun_divisor registros ←%esp r ←%ebp­4 %ebp anterior ←%ebp @retorno/%eip ←%ebp+4 a ←%ebp+8 b ←%ebp+12 result (int *) ←%ebp+16 registros En ambos bloques de activación ahora tenemos un parámetro más (resto/result) que está pasado por referencia.
j) (0.3 ptos) Traduzca a ensamblador IA32 la nueva línea 32 del código.
pushl $mcd          movswl vec(,%esi,2), %ebx   pushl %ebx          pushl mcd           call max_comun_divisor    addl $12, %esp # parametro real &mcd # parametro real vec[i] # parametro real mcd k) (0.3 ptos) Traduzca a ensamblador IA32 la nueva línea 15 del código.
movl %ebp, %ebx subl $4, %ebx         pushl %ebx   pushl 12(%ebp) pushl 8(%ebp) call modulo   # %ebx=%ebp­4 = &r  # parametro real &r # parametro real b # parametro real a # modulo (a,b,&r) 13 addl $12, %esp l) (0.3 ptos) Traduzca a ensamblador IA32 la nueva línea 7 del código.
movl 16(%ebp), %ecx movl 8(%ebp), %ebx movl %ebx, (%ecx) 14 ...