Похожие документы
Gli array. Gli array. Gli array. Classi di memorizzazione per array. Inizializzazione esplicita degli array. Array e puntatori

puntatori Lab. Calc. AA 2007/08 1

Strutture. Strutture e Unioni. Definizione di strutture (2) Definizione di strutture (1)

[MANUALE VISUAL BASIC SCUOLA24ORE PROF.SSA PATRIZIA TARANTINO] 14 dicembre 2008

Allocazione dinamica della memoria - riepilogo

Architettura (10/9/2003) Pag. 1/6. Cognome e Nome (in stampatello):

Funzioni in C. Violetta Lonati

Informatica B. Sezione D. Scuola di Ingegneria Industriale Laurea in Ingegneria Energetica Laurea in Ingegneria Meccanica

Le operazioni di allocazione e deallocazione sono a carico del sistema.

Inizializzazione, Assegnamento e Distruzione di Classi

Fondamenti di Informatica T. Linguaggio C: i puntatori

Dimensione di uno Spazio vettoriale

Le variabili. Olga Scotti

Corso di Fondamenti di Informatica

Concetto di Funzione e Procedura METODI in Java

Strutturazione logica dei dati: i file

Algebra di Boole: Concetti di base. Fondamenti di Informatica - D. Talia - UNICAL 1. Fondamenti di Informatica

Università degli Studi di Cassino Corso di Fondamenti di Informatica Puntatori. Anno Accademico 2010/2011 Francesco Tortorella

Laboratorio di programmazione

INFORMATICA - I puntatori Roberta Gerboni

Fondamenti di Informatica T-1, 2009/2010 Modulo 2 Prova d Esame 5 di Giovedì 15 Luglio 2010 tempo a disposizione 2h30'

Vettori Algoritmi elementari di ordinamento

Definire all'interno del codice un vettore di interi di dimensione DIM, es. int array[] = {1, 5, 2, 4, 8, 1, 1, 9, 11, 4, 12};

Regione Toscana. ARPA Fonte Dati. Manuale Amministratore. L. Folchi (TAI) Redatto da

Introduzione al linguaggio C Gli array

Progetto: ARPA Fonte Dati. ARPA Fonte Dati. Regione Toscana. Manuale Amministratore

Indirizzo di una funzione. Puntatori a funzioni. Definizione di variabili. Definizione di variabili

Esempio: dest = parolagigante, lettere = PROVA dest (dopo l'invocazione di tipo pari ) = pprrlogvgante

dall argomento argomento della malloc()

Lezione 9: Strutture e allocazione dinamica della memoria

(Esercizi Tratti da Temi d esame degli ordinamenti precedenti)

Programmazione dinamica

Tibet4DExt. Manuale Utente. Un Plug-in 4 th Dimension per accedere agli archivi di Tibet in linea. (Versione 1.7.x)

Introduzione al Linguaggio C

Introduzione alla programmazione in C

Variabili e tipi di dato

Matematica - SMID : Programmazione Febbraio 2009 FOGLIO RISPOSTE

Gestione della memoria centrale

4. Operazioni elementari per righe e colonne

I puntatori e l allocazione dinamica di memoria

Il simulatore SPIM SPIM

costruttori e distruttori

Assembler di Spim. Assembler di SPIM. Struttura di un programma assembler. Direttive

Visibilità dei Membri di una Classe

Il tipo di dato astratto Pila

Università degli Studi di Ferrara - A.A. 2014/15 Dott. Valerio Muzzioli ORDINAMENTO DEI DATI

ARRAY BIDIMENSIONALI float [][] mx = new float[3][4]; (float []) [] mx = new float[3][4];

Appello di Informatica B

GaraviniSoftware srl MANUALE IVA. Aggiungere un Codice IVA

CALCOLATORI ELETTRONICI II

Istruzioni per l uso dei programmi MomCad, TraveCon, TraveFon

Università di Torino Facoltà di Scienze MFN Corso di Studi in Informatica. Programmazione I - corso B a.a prof.

Architettura dei calcolatori e sistemi operativi. Assemblatore e Collegatore (Linker) Capitolo 2 P&H Appendice 2 P&H

Calcolare il massimo di una lista

Capitolo Quarto...2 Le direttive di assemblaggio di ASM Premessa Program Location Counter e direttiva ORG

Esercizio: gestione di un conto corrente

Per scrivere una procedura che non deve restituire nessun valore e deve solo contenere le informazioni per le modalità delle porte e controlli

Breve riepilogo della puntata precedente:

LINGUAGGI DI PROGRAMMAZIONE

MATLAB. Caratteristiche. Dati. Esempio di programma MATLAB. a = [1 2 3; 4 5 6; 7 8 9]; b = [1 2 3] ; c = a*b; c

Spiegazione Open Interest Storico:

INFORMATICA 1 L. Mezzalira

La gestione della memoria

DATA BASE ON LINE (BANCA DATI MODULI SPERIMENTALI)

LA CORRISPONDENZA COMMERCIALE

Nell esempio verrà mostrato come creare un semplice documento in Excel per calcolare in modo automatico la rata di un mutuo a tasso fisso conoscendo

Algoritmi e strutture dati. Codici di Huffman

PULSANTI E PAGINE Sommario PULSANTI E PAGINE...1

Dispense di Informatica per l ITG Valadier

MANUALE PARCELLA FACILE PLUS INDICE

Word processor funzione Stampa Unione

AXO Architettura dei Calcolatori e Sistema Operativo. processo di assemblaggio

Alcuni consigli per un uso di base delle serie di dati automatiche in Microsoft Excel

Sistema operativo: Gestione della memoria

Sistemi Operativi IMPLEMENTAZIONE DEL FILE SYSTEM. D. Talia - UNICAL. Sistemi Operativi 9.1

Guida operativa. My Legal Corner. BestSoft SOFTWARE IN SANITÀ

Modello Relazionale dei DBMS - Vincoli Tradizionalmente, esistono quattro modelli logici: Gerarchico Reticolare Relazionale A oggetti XML I modelli

La struttura dati ad albero binario

IL MIO PRIMO SITO NEWS USANDO GLI SCHEDARI

Fondamenti di Informatica 2

MATEMATICA DEL DISCRETO elementi di teoria dei grafi. anno acc. 2009/2010

PROGRAMMA GESTIONE TURNI MANUALE UTENTE. Programma Gestione Turni Manuale Utente versione 1.1

Autorizzazioni Kronos Web

SISTEMI DI NUMERAZIONE E CODICI

Excel. A cura di Luigi Labonia. luigi.lab@libero.it

La Stampa Unione. Individuare la lista indirizzi per la Stampa Unione

Appunti tratti dal videocorso on-line di Algoritmi e Programmazione Avanzata By ALeXio

Algoritmi e Strutture Dati

strutturare dati e codice

Sistemi Operativi IMPLEMENTAZIONE DEL FILE SYSTEM. Implementazione del File System. Struttura del File System. Implementazione

Moduli (schede compilabili) in Word Esempio: scheda di alimentazione per un degente

MIPS Instruction Set 2

1 Applicazioni Lineari tra Spazi Vettoriali

Tabelle Pivot - DISPENSE

Scrivere uno script php che, dato un array associativo PERSONE le cui chiavi sono i

Транскрипт:

Strutture dati in C e loro traduzione in assembler MIPS 1 Direttive assembler per l'allocazione dei dati Prima di iniziare a trattare il problema dell'allocazione delle varie strutture dati, introduciamo le direttive assembler che servono per allocare dati globali nel segmento dei dati, ovvero successivamente alla direttiva.data. Le direttive hanno a che fare con dati di tipo elementare (int, float, double, char), e possono essere impiegati anche per allocare sequenze di dati elementari gia inizializzati oppure non inizializzati. E' possibile specicare, prima delle direttive stesse, delle etichette seguite dai due punti. Le etichette di fatto corrispondono agli indirizzi di memoria in corrispondenza dei quali i dati verranno allocati dall'assemblatore. Le etichette possono poi essere usare dalle istruzioni per far riferimento alle aree di memoria relative, ad esempio possono essere riferite dalle istruzioni di lw e sw per leggere e scrivere, rispettivamente, in memoria. Le principali direttive per l'allocazione di dati inizializzati sono le seguenti:.half h1,...,hn # dich. di una sequenza di n half-word;.word w1,...,wn # dich. di una sequenza di n word (interi).byte b1,...,bn # dich. di una sequanza di byte.float f1,...,fn # dich. di una sequenza di float.double d1,...,dn # dich. di una sequenza di double.asciiz str # dich. di una stringa costante (terminata da 0) dove le liste alla destra delle direttive corrispondono alle inizializzazioni delle rispettive locazioni di memoria. I vari elementi delle liste sono allocati in memoria in locazioni contigue. Gli indirizzi dei vari elementi sono scelti in modo da rispettare degli allineamenti pressati. In particolare.half alloca i vari elementi su indirizzi multipli di 2, mentre.word,.float e.double su indirizzi multipli di 4. Le direttive.byte e.asciiz, poiche allocano dati di lunghezza 1B, non devono rispettare alcun allineamento. Si noti che lw/sw devono essere usati per accedere dati (4B) allineati alla parola (ind. multipli di 4), lh/sh per accedere dati (2B) allineati alla mezza parola (ind. multipli di 2), ed inne lb/sb per accedere dati (1B) allineati al byte. 1

Se l'indirizzo impiegato non rispetta l'allineamento relativo, si ottiene un'errore (eccezione causata da allineamento errato). La direttiva.align n puo invece essere impiegata per rompere lo schema di allineamento automatico imposto dalla direttiva seguente. In particolare, essa impone che il prossimo dato venga allineato con un indirizzo multiplo di 2 n. Quindi.align 2 impone l'allineamento alla parola, mentre.align 0 rimuove tutti gli allineamenti automatici imposti da.half,.word, ecc. Inne, la direttiva.space n alloca uno spazio di n byte nel segmento dei dati. L'allineamento ssato da.space puo essere controllato con la direttiva.align vista sopra. 2 Array mono-dimensionali (vettori) Si considerino i due vettori seguenti: int a[10]; char b[5]; Essi possono essere allocati in memoria rispettando gli allineamenti con le seguenti direttive:.data.align 2 a:.space 40 b:.space 5 Gli elementi dei due array sono allocati in memoria in maniera contigua. Tramite la direttiva.align 2 abbiamo forzato l'allineamento dei vari elementi dell'array a[] alla word (4B). Per esempio, se i due array sono allocati il primo a partire dall'indirizzo 0, il secondo dall'indirizzo 40, abbiamo il seguente layout di memoria: ------------------------------------------------------- a[0] a[1]... ------------------------------------------------------- 0 4 8 ------------------------------------------------------- b[0] b[1] b[2] b[3] b[4] b[5] b[6]... ------------------------------------------------------- 40 41 42 43 44 45 46 47 I due esempi seguenti illustrano un paio di funzioni C, con relativa traduzione MIPS, che restituiscono il valore dell'elemento di indice ind di un array di interi e di caratteri. Relativamente al codice assembler illustrato in Esempio 2.1, si noti la moltiplicazione per 4 (sll $a1, $a1, 2), che serve per tener conto della dimensione degli interi (4B). 2

Esempio 2.1 int elem(int a[], int ind) return(a[ind)); elem: sll $a1, $a1, 2 add $v0, $a0, $a1 lw $v0, 0($v0) La funzione e scritta in accordo alla politica caller-save. I parametri a e ind sono passati rispettivamente in $a0 e $a1. Il risultato della funzione e Esempio 2.2 char elem(char a[], int ind) return(a[ind)); elem: add $v0, $a0, $a1 lb $v0, 0($v0) La funzione e scritta in accordo alla politica caller-save. I parametri a e ind sono passati rispettivamente in $a0 e $a1. Il risultato della funzione e 3 Array bi-dimensionali La convenzione impiegata dal compilatore C per allocare array bi-dimensionali in memoria lineare e' quella di memorizzare il vettore per righe. Ovvero, prima tutti gli elementi della riga 0, di seguito e in maniera contigua tutti quelli della riga 1, ecc. Si consideri ad esempio l'array: int a[10][2]; che puo essere allocato in memoria rispettando gli allineamenti con le seguenti direttive:.data.align 2 a:.space 80 L'arraye poi allocato in memoria dall'assemblatore a partire da un indirizzo multiplo di 4. Se il primo elemento della prima riga (a[0][0]) e allocato a partire dall'indirizzo 0, abbiamo il seguente layout: ----------------------------------------------------------------------- a[0][0] a[0][1] a[1][0]... ----------------------------------------------------------------------- 0 4 8 12 Per accedere l'elemento a[i][j] e quindi necessario calcolare il displacement a partire dall'indirizzo corrispondente all'etichetta a. Si consideri, a proposito, che il primo elemento della riga i-esima, a meno di 3

calcoli che riguardano la dimensione del dato, e memorizzato a partire dal displacement: i*num colonne. Per selezionare l'elemento j-esimo della riga medesima basta quindi sommare j al displacement precedente, ottenendo quindi un diplacement uguale a: i*num colonne+j. Poiche nel processore MIPS l'indirizzamento e al Byte, per avere il displacement corretto bisogna anche moltiplicare per la dimensione del tipo di dato dell'array stesso: (i*num colonne+j)*size. Esempio 3.1 int el2(int a[][2], int i1, int i2) return(a[i1][12)); el2: sll $t0, $a1, 3 # i1*8 sll $t1, $a2, 1 # i2*2 addu $t0, $a0, $t0 addu $t0, $t1, $t0 lw $v0, 0($t0) La funzione e scritta in accordo alla politica caller-save. I parametri a e i1 e i2 sono passati, rispettivamente, in $a0, $a1 e $a2. Nel calcolo del displacement da sommare a $a0 bisogna considerare che num colonne=2, mentre size=4, per cui l'espressione (i*num colonne+j)*size diventa i*8+j*2. Il risultato della funzione e 4 Strutture Attraverso le struct e possibile in C denire collezioni di dati di tipo diverso, e riferire tali collezioni con uno stesso nome. Ad esempio, questa e una denizione di struttura C: struct elem int i[2]; double d; ; Alternativamente: typedef struct int i[2]; double d; type_elem; Nel primo caso, per denire una nuova variabile var di tipo struct elem, basta dichiararla come segue: 4

struct elem var; mentre nel secondo caso, avendo ridenito un nuovo tipo type elem, basta dichiararla come segue: type_elem var; Nel seguito useremo sempre la prima convenzione, senza usare typedef. L'allocazione della variabile var di tipo struct elem in memoria prevede l'allocazione contigua dei vari campi della struttura a partire da un indirizzo di partenza. Solitamente i vari campi della struttura vengono pero allocati in memoria rispettando l'allineamento denito dai tipi associati ai campi stessi. Questo puo portare ad alcuni sprechi di spazio tra un campo e l'altro. Ad esempio, se gli int e i double devono essere allineati alla word (4B), la variabile var di tipo struct elem verra cos memorizzata (considerando che il primo campo della struttura e allocato a partire dall'indirizzo 0): c //// i[0] i[1] d... 0 4 8 12 16 20 sprecando 3B in piu per l'allineamento tra il campo c ed il campo i[]. Inoltre, poichee possibile denire array di strutture, sempre per rispettare gli allineamenti e spesso necessario sprecare spazio tra una struttura e la successiva all'interno dell'array. Ad esempio, se deniamo il seguente array ar[], i cui elementi sono di tipo struct elem: struct elem int k; ; struct elem ar[10]; l'array verra cos memorizzato (considerando che il primo campo elemento dell'array sia allocato a partire dall'indirizzo 128, per cui l'etichetta ar corrispondera a 128): k c ///// k c ///// k... 128 132 136 140 144 148 La dimensione della struttura sara quindi 8B, considerando i byte nali (padding), che garantiscono l'allineamento del prossimo elemento dell'array, come parte integrante della struttura stessa. Questo tipo di gestione della memoria puo essere vericato da C tramite il seguente comando: 5

printf("%d\n", sizeof(struct elem)); Possimo ora dare una regola generale per scegliere l'allineamento dell'indirizzo iniziale di una struttura e garantire che: tutti i campi della struttura sia allineati opportunamente; l'indirizzo della struttura stessa sia anche l'indirizzo del primo campo della struttura stessa; i vari campi della struttura si possano individuare tramite un displacement costante a partire dall'indirizzo iniziale. Per eettuare questa scelta, basta considerare i tipi di tutti i campi contenuti nella struttura, scegliendo come allineamento dell'indirizzo iniziale della struttura l'allineamento piu severo tra quelli deniti dai vari campi della struttura stessa. Per esempio, se abbiamo un campo char (allineamento a 1B), un campo short int (allineamento a 2B), ed un campo int (allineamento a 4B), l'indirizzo iniziale della struttura dovra essere un multiplo di 4 (allineamento alla word=4b). 4.1 Accesso ai campi delle strutture Si consideri la seguente struttura: struct elem int i[2]; double d; ; In accordo alla regola data precedentemente, se i double devono essere allianeati alla word, l'indirizzo iniziale di una variabile di tipo struct elem deve essere anch'esso allineato alla word. Considerando che questo indirizzo iniziale sia 128: c ////// i[0] i[1] d... 128 132 136 140 144 148 Vediamo ora tre semplici esempi di funzioni che accedono ai vari campi di una struttura di tipo struct elem, il cui puntatore e passato come parametro delle funzioni stesse. Esempio 4.1 char ret_c(struct elem *ptr) return( ptr->c ); ret_c: lb $v0, 0($a0) La funzione e scritta in accordo alla politica caller-save. Il parametro ptr e passato in $a0. Il risultato della funzione e 6

Esempio 4.1.2 int *ret_i(struct elem *ptr) return( ptr->i ); /* Il comando di sopra e' equivalente a: return ( &(ptr->i[0]) ); */ Esempio 4.1.3 ret_i: addiu $v0, $a0, 4 La funzione e scritta in accordo alla politica caller-save. Il parametro ptr e passato in $a0. Il risultato della funzione e int ret_i1(struct elem *ptr) return( ptr->i[1] ); ret_i1: lw $v0, 4($a0) 4.2 Campi puntatore all'interno di strutture La funzione e scritta in accordo alla politica caller-save. Il parametro ptr e passato in $a0. Il risultato della funzione e La struttura denita precedentemente aveva come caratteristica che il vettore di interi int i[2] era completamente contenuto all'interno della struttura ed aveva lunghezza ssa. Se invece volessimo implementare una lista di strutture dove, per ogni struttura, il vettore i[] avesse lunghezza variabile, in C dovremmo dichiarare: struct elem int *i; double d; ; Se poi volessimo, a tempo di esecuzione, allocare un vettore di due interi, puntato dal puntatore i contenuto all'interno di una variabile di tipo struct elem, dovremmo scrivere:... struct elem var;... var.i = (struct elem *) malloc(2 * sizeof(int)); dove malloc(2 * sizeof(int)) alloca un'area di memoria contigua (di cui restituisce l'indirizzo) di dimensione 8B. Considerando che la variabile var deve essere allineata alla word (es. 128), e che l'area di memoria restituita da malloc() sia anch'essa allineata alla word 7

(es. 1024), l'assegnamento di sopra (var.i =...) produrrebbe la seguente situazione: c ////// i=1024 d... --------------------- --------------------------------------------------- 128 132 136 140 144 148 \/ --------------------------- i[0] i[1] --------------------------- 1024 1028 Nota che, anche se abbiamo cambiato la denizione della struttura, per riferire l'indirizzo dell'array i[] continueremo ad usare la notazione var.i, mentre per riferire il secondo elemento dell'array i[] continueremo ad usare la notazione var.i[1]. La traduzione assembler e invece completamente diversa. Per illustrare questo, rivediamo due degli esempi visti precedentemente: Esempio 4.1.2 ed Esempio 4.1.3. Negli esempi rivisti, la denizione di struct elem e quella nuova, con l'array i[] allocato dinamicamente a tempo di esecuzione. Esempio 4.2.1 int *ret_i(struct elem *ptr) return( ptr->i ); /* Il comando di sopra e' equivalente a: return ( &(ptr->i[0]) ); */ ret_i: lw $v0, 4($a0) La funzione e scritta in accordo alla politica caller-save. Il parametro ptr e passato in $a0. Il risultato della funzione e Esempio 4.2.2 int ret_i1(struct elem *ptr) return( ptr->i[1] ); ret_i1: lw $v0, 4($a0) lw $v0, 4($v0) La funzione e scritta in accordo alla politica caller-save. Il parametro ptr e passato in $a0. Il risultato della funzione e 8