Cuarta Experiencia. Laboratorio de Estructuras de Computadores 02/2001 Preparación previa. Estructuras dinámicas de datos. Solicitación de memoria. Se estudia una lista simplemente enlazada, ésta está formada por un conjunto de nodos. Cada nodo es una estructura(struct en C) formada por un puntero y un entero. /* Declaración del nodo para la lista enlazada */ struct node { struct node *next; /* puntero al siguiente nodo */ int value; /* espacio para almacenar un valor entero */ }; Los nodos se enlazan empleando el campo next(próximo) del nodo. El último nodo de la lista tiene un valor nulo(valor cero) en el campo next. Se emplea la lista para mantener un conjunto ordenado de enteros. Es decir, el entero más negativo está almacenado en el primer nodo de la lista, y el positivo mayor en el último nodo de la lista. En los apuntes de clases existe una breve introducción al lenguaje C, en el que se estudia una lista simplemente enlazada. El siguiente programa en C, ilustra las funciones: newnode que crea una nueva instancia de un nodo y lo coloca en el lugar correcto de la lista. printlist que imprime la secuencia de valores almacenados en la lista. main: prueba las funciones anteriores. Además se emplea una variable estática list, desde la cual se cuelga la lista obtenida en forma dinámica. En esta situación se está obligado a emplear un puntero. En el momento de la compilación y carga del programa en memoria, sólo se tiene el espacio para la variable list. Luego, durante la ejecución, el espacio dinámico se asocia al puntero list. static struct node *list = 0; /* puntero al primer nodo de la lista */ /* Mantiene la lista de enteros ordenada. Colocando cada nuevo elemento en su lugar*/ void newnode (int value) { struct node *temp = ( struct node *) malloc(sizeof(*temp)); /* Nótese que el tamaño en bytes se calcula con: sizeof(*temp) == sizeof(struct node) */ struct node *aptr, *bptr; temp->value = value; /* enlaza el item en el lugar correcto */ aptr = ( struct node *) &list; /* el cast es necesario, sino habría tipos incompatibles */ bptr = list; Laboratorio de Estructuras de Computadores. Lab04 14-08-2001 1 while ((bptr!=0) && (bptr->value < value)) { aptr = bptr; bptr = bptr->next; } aptr->next = temp; temp->next = bptr; } /* Imprime los enteros de la lista. */ void printlist(void) { struct node *ptr; ptr = list; while (ptr != 0) { printf("%d\n", ptr->value); ptr = ptr->next; } } /* La función principal prueba la función newnode. */ int main (void) { newnode(5); newnode(1); lista newnode(0); newnode(6); newnode(-1); newnode(10); -1 0 1 5 6 10 printlist(); } El resultado correcto de la impresión debe ser: -1 0 1 5 6 10 # En el código assembler de malloc se emplea un llamado al sistema. # Esta versión deja la zona iniciada con puros unos. # a0 debe ser el tamaño en bytes que se asignará. # en v0 se retorna un puntero a la zona asignada. Laboratorio de Estructuras de Computadores. Lab04 14-08-2001 2 malloc: # extend memory size # li $v0,9 # código para sbrk syscall # retorna una zona iniciada con ceros # beq addiu addu ori sb j l1: listo: jr $ra $a0,$0,listo $a0,$a0,-1 $t0,$a0,$v0 $t1, $t1, 0xff $t1,0($t0) l1 # mientras queden en la zona # a0-# t0 apunta a un byte de la zona # t1 = 0xFF # setea el byte con puros unos # continue # el valor de v0 es el retorno del syscall brk En el Laboratorio. • Compilar y ejecutar en C. Si es necesario, agregar algunos printf para observar variables; o bien, correr paso a paso, empleando un depurador y observando variables(inspect o watch). • Escribir el programa en assembler MIPS. Ejecutarlo en SPIM observando la ejecución de las rutinas. • Empleando lcc, compilar el texto en C, e introducir las rutinas assembler para malloc y printf. Laboratorio de Estructuras de Computadores. Lab04 14-08-2001 3