CORRISPONDENZA C++ ASSEMBLER G. Frosini Corrispondenza C++ Assembler Slide 1
G. Frosini Corrispondenza C++ Assembler Slide 2 Funzione C++ Funzione C/C++ (o sottoprogramma): può avere parametri formali; può avere variabili interne; può restituire un valore. Chiamata di una funzione: i parametri attuali dipendono dalle regole di visibilità del blocco chiamante; la funzione chiamata ha le regole di visibilità del blocco chiamato stesso, che possono essere diverse da quelle del blocco chiamante. ... void primo (int* a) { int aa; ... aa = 1; *a = 2 + * a; ... } void secondo (int b) { int bb; ... primo (&b); primo (&bb); ... G. Frosini Corrispondenza C++ Assembler Slide 2
Tempo di vita delle variabili C++ Variabili globali: hanno lo stesso tempo di vita del programma (variabili statiche). Variabili locali di una funzione: esistono per il tempo di esecuzione della funzione stessa (variabili automatiche); le variabili locali definite nei vari blocchi di una medesima funzione hanno tutte lo stesso tempo di vita; ogni esecuzione della funzione ha la propria copia di variabili locali. Parametri di una funzione: hanno lo stesso tempo di vita delle variabili locali; quando inizia l’esecuzione di una funzione, i parametri formali nascono e vengono inizializzati con i parametri attuali. Variabili create e distrutte dinamicamente: per adesso non vengono prese in considerazione. G. Frosini Corrispondenza C++ Assembler Slide 3
Livello dinamico di un’istanza In un programma, una funzione può essere eseguita più volte. Funzione in esecuzione: istanza di quella funzione. Livello dinamico di una istanza: numero di istanze non ancora terminate (di quella funzione o di altre funzioni), a partire dalla prima (ed unica) istanza della funzione main, alla quale si associa il livello dinamico 0. Istanze (di una stessa funzione o di funzioni differenti): una istanza inizia (necessariamente) dopo l'istanza che la manda in esecuzione e termina prima di quest’ultima; le istanze vanno in esecuzione con la regola LIFO (Last In, First Out). G. Frosini Corrispondenza C++ Assembler Slide 4
Ambiente di un’istanza Ambiente di una istanza: insieme degli oggetti riferibili da una istanza di funzione: si compone di due parti: ambiente globale (insieme delle variabili globali e delle funzioni); ambiente locale (insieme dei parametri attuali e delle variabili automatiche propri di quella istanza). Specifica istanza: i parametri formali sono differenti da istanza a istanza, e vengono inizializzati con i parametri attuali di quella istanza; le variabili automatiche sono differenti da istanza a istanza (anche se hanno lo stesso nome). Osservazioni sulle regole di visibilità: hanno effetto in fase di compilazione, e possono imporre delle restrizioni all’ambiente: gli oggetti effettivamente riferibili da parte di un blocco possono essere un sottoinsieme dell’ambiente stesso; agiscono in base alla natura testuale del programma; sono delle regole statiche. G. Frosini Corrispondenza C++ Assembler Slide 5
Forma dell’ambiente locale varia da istanza a istanza, anche per una stessa funzione; entità dinamica. Forma dell’ambiente locale: uguale per tutte le istanze di una stessa funzione: è uguale il numero e tipo dei parametri formali; è uguale il numero e tipo delle variabili locali; entità statica. G. Frosini Corrispondenza C++ Assembler Slide 6
G. Frosini Corrispondenza C++ Assembler Slide 7 Esempi di ambiente void primo (int* a) { int aa; ... aa = 1; *a = 2 + *a; ... } void secondo (int b) { int bb; ... primo (&b); primo (&bb); ... Istanze di primo (due istanze): ambiente globale: variabili globali e funzioni; ambiente locale della prima istanza: parametro attuale a=&b, variabile locale aa; ambiente locale della seconda istanza: parametro attuale a=&bb, variabile locale aa (diversa dalla precedente). Osservazione: nell’ambiente possono esserci anche entità non visibili (nella seconda istanza di primo, la variabile bb). G. Frosini Corrispondenza C++ Assembler Slide 7
Riferimento all’ambiente Funzione: ha una singola copia di codice; Istanza di funzione: ha un proprio ambiente locale. Il codice deve riferire: tutte le funzioni (ambiente globale); le variabili globali (ambiente globale); i parametri attuali e le variabili locali di quella istanza (ambiente locale). Entità globale: si riferisce con un indirizzo assoluto. Entità locale: si riferisce con un indirizzo relativo, costituito da un indirizzo base, che individua l'ambiente locale attuale, e da uno spiazzamento (displacement), che individua l‘entità all’interno dell'ambiente e che è invariante per tutte le istanze. G. Frosini Corrispondenza C++ Assembler Slide 8
Record di attivazione (1) Istanza di funzione: costruzione sulla pila di un record di attivazione (o frame), che contiene le informazioni utili per quella istanza. Record di attivazione: utilizza un registro (registro base o puntatore), che contiene l'indirizzo base del record e che individua l'ambiente locale. Costruzione di un nuovo record di attivazione: il valore del registro base viene salvato e successivamente ripristinato quando il record di attivazione costruito viene distrutto. Informazioni contenute nel record di attivazione: parametri attuali; indirizzo di ritorno alla funzione chiamante (tale indirizzo viene messo in pila per effetto della istruzione di chiamata); link dinamico, destinato a memorizzare il vecchio valore del registro base (contiene l'indirizzo base del record di attivazione dinamicamente precedente); spazio per le variabili locali. G. Frosini Corrispondenza C++ Assembler Slide 9
Record di attivazione (2) Costruzione del record di attivazione: iniziata dalla funzione chiamante; completata dalla funzione chiamata (mediante un apposito prologo). Il chiamante inserisce in pila: i parametri attuali; l'indirizzo di ritorno (istruzione CALL). Il chiamato inserisce in pila: il link dinamico; lo spazio per le variabili locali. Indirizzo base: stabilito dal chiamato; corrisponde ad un punto intermedio del record di attivazione, punto che separa i parametri attuali dalle variabili locali (coincide con l'indirizzo del link dinamico del record di attivazione); i parametri attuali vengono riferiti con displacement positivi e le variabili locali con displacement negativi. G. Frosini Corrispondenza C++ Assembler Slide 10
Record di attivazione (3) G. Frosini Corrispondenza C++ Assembler Slide 11
Record di attivazione (4) Distruzione del record di attivazione: iniziata dal chiamato (mediante un apposito epilogo); completata dal chiamante. Il chiamato rimuove dalla pila: lo spazio per le variabili locali; il link dinamico; l'indirizzo di ritorno (istruzione RET). Il chiamante rimuove dalla pila: lo spazio per i parametri attuali. G. Frosini Corrispondenza C++ Assembler Slide 12
Record di attivazione e sua forma Record di attivazione di una funzione: parametri attuali; indirizzo di ritorno specifico; link dinamico specifico; indirizzi base specifico; copia specifica di variabili locali. Forma dei record di attivazione di una funzione (dipendente solo dalla natura statica della funzione stessa): parametri formali; indirizzo di ritorno generico; link dinamico generico; indirizzo base generico; copia standard di variabili locali. G. Frosini Corrispondenza C++ Assembler Slide 13
Parametri valore (e valore-indirizzo) Parametri trasmessi per valore: un parametro formale di un dato tipo viene ad assumere un valore (parametro attuale) dello stesso tipo. Valori che rappresentano indirizzi: il valore trasmesso rappresenta un indirizzo: questo accade, per esempio, quando il parametro formale è un puntatore, e il valore trasmesso è l’indirizzo dell’oggetto puntato; si ha una trasmissione per valore-indirizzo (brevemente, per indirizzo). Parametri array: un array corrisponde all’indirizzo del primo elemento; un parametro formale di tipo array è un puntatore; un array è trasmesso per indirizzo. Nota: un parametro formale di tipo struttura viene trasmesso per valore: se questa è formata da un array, il corrispondente parametro attuale è dato dal valore di tutta la struttura, ossia dal valore dell’intero array (array trasmesso per valore e non per indirizzo). G. Frosini Corrispondenza C++ Assembler Slide 14
G. Frosini Corrispondenza C++ Assembler Slide 15 Risultato di funzioni Una funzione non void restituisce: un valore un valore-indirizzo. (non consideriamo al momento valori di un tipo struttura o unione) Questo viene posto: in AL se il valore è di tipo carattere; in EAX se il valore è di tipo intero (o di tipo enumerato); in ST (FPU) se il valore è di tipo reale. in EAX se trattasi di un valore-indirizzo (come il valore di un puntatore); G. Frosini Corrispondenza C++ Assembler Slide 15
Interfaccia del chiamante Quando deve essere eseguita una funzione, il chiamante effettua delle azioni di interfaccia: azioni iniziali (chiamata in senso lato): immissione in pila dei parametri attuali, in ordine inverso rispetto a quello che compare nella istruzione di chiamata; esecuzione dell’istruzione di chiamata; azioni al ritorno: eliminazione dalla pila dello spazio occupato dai parametri attuali. G. Frosini Corrispondenza C++ Assembler Slide 16
Interfaccia del chiamato Una funzione (il chiamato) effettua delle azioni di interfaccia (viene utilizzato il registro EBP per memorizzare l’indirizzo base del record di attivazione attuale): prologo: salvataggio in pila del contenuto del registro EBP (costruzione del link dinamico); ricopiamento nel registro EBP del valore attuale del registro ESP (questo è l'indirizzo base del record di attivazione attuale; riserva di spazio in pila per le variabili locali (eventuali variabili di lavoro della funzione, non visibili a livello di linguaggio C/C++, rientrano in questa categoria). epilogo: eliminazione dalla pila dello spazio riservato alle variabili locali; ripristino del contenuto del registro EBP; effettuazione del ritorno al chiamante (istruzione RET). G. Frosini Corrispondenza C++ Assembler Slide 17
Utilizzo di parametri attuali e di variabili locali Dopo l'esecuzione del prologo risulta completamente costruito il record di attivazione di quella istanza di funzione. Indirizzi relativi: i parametri attuali e le variabili locali vengono riferiti con un indirizzamento a registro base rispetto a EBP; displacement positivi per i parametri; displacement negativi per le variabili locali. Indirizzi assoluti: solo per riferire l'ambiente globale. Nota: tutte le variabili devono risiedere in memoria (la pila è una zona di memoria); nel corpo della funzione si possono temporaneamente utilizzare tutti i registri generali (tranne EBP ed ESP), provvedendo inizialmente a salvare il loro contenuto e alla fine a ripristinarlo. G. Frosini Corrispondenza C++ Assembler Slide 18
Prologo ed Epilogo del chiamato (Assembler) PUSHL %EBP # link dinamico MOVL %ESP, %EBP # indirizzo base record di attivazione SUBL $v, %ESP # spazio per le variabili locali (v byte) Epilogo: MOVL %EBP, %ESP # eliminazione spazio per variabili locali POPL %EBP # ripristino del vecchio indirizzo base RET # ritorno al chiamante ovvero (altro epilogo): LEAVE G. Frosini Corrispondenza C++ Assembler Slide 19
Indirizzamenti del chiamato (Assembler) I parametri vengono riferiti in questo modo (PARi = ... , 12, 8): # parametro: valore di intero da portare in EAX MOVL PARi(%EBP), %EAX # parametro: indirizzo di intero da portare in EAX MOVL PARi(%EBP), %EBX MOVL (%EBX), %EAX # risultato: prodotto in EAX e memorizzato # utilizzando un parametro indirizzo di intero MOVL %EAX, (%EBX) Le variabili locali vengono riferite in questo modo (VARj = -4, -8, ...): # risultato: prodotto in EAX # e memorizzato in una variabile locale MOVL %EAX, VARj(%EBP) G. Frosini Corrispondenza C++ Assembler Slide 20
Interfaccia del chiamante: variabili globali Parametri attuali del chiamato: costituiti da variabili globali. # valore di variabile globale aa intera PUSHL aa # indirizzo di variabile globale bb intera LEAL bb, %EAX PUSHL %EAX ovvero PUSHL $bb ... # istruzione di chiamata del sottoprogramma sott CALL sott # eliminazione spazio per i parametri attuali (n byte) ADDL $n, %ESP G. Frosini Corrispondenza C++ Assembler Slide 21
G. Frosini Corrispondenza C++ Assembler Slide 22 Esempio 1 - Versione C++ // file ese1a.cpp extern "C" int fai (int a, int b, int* c) { int d; // … d = a + 1; *c = a + b; // ... return d; } // file es1b.cpp extern "C" int fai(int a, int b, int* c); int alfa, beta, gamma; int main () { int d; d = fai (alfa, beta, &gamma); return 0; G. Frosini Corrispondenza C++ Assembler Slide 22
Forma del Record di attivazione di fai() G. Frosini Corrispondenza C++ Assembler Slide 23
Esempio1 - Versione Assembler (1) # file ese1a.s .GLOBAL fai .TEXT fai: PUSHL %EBP # prologo MOVL %ESP, % EBP SUBL $4, % ESP # int d PUSHL %EBX MOVL 8(%EBP), %EAX # a INCL %EAX MOVL %EAX, -4(%EBP) # d = a + 1 MOVL 16(%EBP), %EAX # c (&) MOVL 8(%EBP), %EBX # a ADDL 12(%EBP), %EBX # a + b MOVL %EBX,(%EAX) # *c = a + b MOVL -4(%EBP) ,%EAX # return d POPL %EBX LEAVE # epilogo RET G. Frosini Corrispondenza C++ Assembler Slide 24
Esempio1 - Versione Assembler (2) # file es1b.s .DATA .GLOBAL alfa, beta, gamma alfa: .LONG 0 beta: .LONG 0 gamma: .LONG 0 .TEXT .GLOBAL main .EXTERN fai main: PUSHL %EBP MOVL % ESP, % EBP SUBL $4, %ESP # d # ... PUSHL $gamma PUSHL beta PUSHL alfa CALL fai ADDL $12,%ESP MOVL %EAX, -4(%EBP) # ... XORL %EAX, %EAX LEAVE RET G. Frosini Corrispondenza C++ Assembler Slide 25
G. Frosini Corrispondenza C++ Assembler Slide 26 Programmi eseguibili Si può ottenere un programma eseguibile (nel file a.out) in uno di questi quattro modi possibili: g++ -m32 ese1a.cpp ese1b.cpp g++ -m32 ese1a.cpp ese1b.s g++ -m32 ese1a.s ese1b.cpp g++ -m32 ese1a.s ese1b.s G. Frosini Corrispondenza C++ Assembler Slide 26
Interfaccia del chiamante: parametri e variabili locali Parametri attuali del chiamato: costituiti da parametri e variabili locali del chiamante # parametro valore intero trasmesso per valore PUSHL PARi(%EBP) # parametro valore intero trasmesso per indirizzo LEAL PARi(%EBP), %EAX PUSHL %EAX # parametro indirizzo di intero trasmesso per valore MOVL PARi(%EBP), %EAX PUSHL (%EAX) # parametro indirizzo di intero trasmesso per indirizzo # variabile locale intera trasmessa per valore PUSHL VARj(%EBP) # variabile locale intera trasmessa per indirizzo LEAL VARj(%EBP), %EAX G. Frosini Corrispondenza C++ Assembler Slide 27
G. Frosini Corrispondenza C++ Assembler Slide 28 Esempio 2 - Versione C++ // file ese2a.cpp extern "C" void uno (int h, int k, int* r) { *r = h + k; } extern "C" void due (int a, int* b) { int aa; *b = 10; uno (a, *b, &a); uno (a, *b, &aa); uno (a, aa, b); // file ese2b.cpp extern "C" void due(int a, int*b); int alfa, beta; int main () { due (alfa, &beta); // ... return 0; G. Frosini Corrispondenza C++ Assembler Slide 28
Forma del record di attivazione di uno() e di due() G. Frosini Corrispondenza C++ Assembler Slide 29
Esempio 2 - Versione Assembler (1) # file ese2a.s .GLOBAL uno, due .TEXT uno: PUSHL %EBP # prologo MOVL %ESP, %EBP PUSHL %EAX PUSHL %EBX MOVL 16(%EBP), %EAX # r(&) MOVL 8(%EBP), %EBX # h ADDL 12(%EBP), %EBX # h + k MOVL %EBX, (%EAX) # *r = h + k POPL %EBX POPL %EAX LEAVE # epilogo RET G. Frosini Corrispondenza C++ Assembler Slide 30
Esempio 2 - Versione Assembler (2) # segue file ese2a.s due: PUSHL % EBP # prologo MOVL %ESP, % EBP SUBL $4, %ESP # aa PUSHL %EAX MOVL 12(%EBP), %EAX # b(&) MOVL $10, (%EAX) # *b = 10 LEAL 8(%EBP), %EAX # uno (a, *b, &a) PUSHL %EAX MOVL 12(%EBP), %EAX PUSHL (%EAX) PUSHL 8(%EBP) CALL uno ADDL $12, %ESP G. Frosini Corrispondenza C++ Assembler Slide 31
Esempio 2 - Versione Assembler (3) # segue file ese2a.s LEAL -4(%EBP), %EAX # uno (a, *b, &aa) PUSHL %EAX MOVL 12(%EBP), %EAX PUSHL (%EAX) PUSHL 8(%EBP) CALL uno ADDL $12,%ESP PUSHL 12(%EBP) # uno (a, aa, b) PUSHL -4(%EBP) PUSHL 8(%EBP) ADDL $12, %ESP POPL %EAX LEAVE # epilogo RET G. Frosini Corrispondenza C++ Assembler Slide 32
Esempio 2 - Versione Assembler (4) # file ese2b.s .DATA .GLOBAL alfa, beta alfa: .LONG 0 beta: .LONG 0 .TEXT .EXTERN due .GLOBAL main main: PUSHL %EBP MOVL %ESP, %EBP #... PUSHL $beta # due (alfa, &beta); PUSHL alfa CALL due ADDL $8, %ESP # ... XORL %EAX, %EAX LEAVE RET G. Frosini Corrispondenza C++ Assembler Slide 33
Esempio 2: programmi ottenibili Si può ottenere un programma eseguibile (nel file a.out) in uno di questi quattro modi possibili: g++ -m32 ese2a.cpp ese2b.cpp g++ -m32 ese2a.cpp ese2b.s g++ -m32 ese2a.s ese2b.cpp g++ -m32 ese2a.s ese2b.s G. Frosini Corrispondenza C++ Assembler Slide 34
Funzioni che restituiscono strutture (o unioni) Funzione chiamante: individua l’indirizzo a partire dal quale deve essere lasciato il risultato (comunemente quello di una sua variabile locale, non visibile al programmatore); inserisce tale indirizzo in pila, come ulteriore primo parametro (che quindi immette in pila per ultimo); dopo l’istruzione di chiamata, provvede a ripulire la pila eliminando lo spazio occupato dai parametri specificati dall’utente, senza considerare il parametro aggiuntivo. Funzione chiamata: riferisce i parametri specificati dall’utente tenendo conto di questo primo ulteriore parametro (aggiunge sempre 4 al displacement); lascia in EAX l’indirizzo del risultato (specificato dal chiamante come ulteriore primo parametro); ritorna al sottoprogramma chiamante, eliminando dalla pila lo spazio occupato dall’indirizzo del risultato (istruzione ret $4). G. Frosini Corrispondenza C++ Assembler Slide 35
Esempio con strutture (1) // file eseas.cpp struct due { int n; int nn; }; extern "C" due fun(int a, int b) { due st; st.n = a + b; st.nn = a - b; return st; } // file esebs.cpp extern "C" due fun(int a, int b); int main () { int aa, bb; due dd; // ... dd = fun(aa, bb); return 0; G. Frosini Corrispondenza C++ Assembler Slide 36
Esempio con strutture (2) # file eseas.s .GLOBAL fun .TEXT fun: PUSHL %EBP MOVL %ESP, %EBP SUBL $8,%ESP # st PUSHL %EDX MOVL 8(%EBP), %EAX # indirizzo risultato in eax MOVL 12(%EBP), %EDX # a ADDL 16(%EBP), %EDX # b MOVL %EDX, -8(%EBP) # st.n MOVL 12(%EBP), %EDX SUBL 16(%EBP), %EDX MOVL %EDX, -4(%EBP) # st.nn MOVL -8(%EBP), %EDX MOVL %EDX, (%EAX) MOVL -4(%EBP), %EDX MOVL %EDX, 4(%EAX) POPL %EDX LEAVE RET $4 G. Frosini Corrispondenza C++ Assembler Slide 37
Esempio con strutture (3) # file esebs.s .EXTERN fun .GLOBAL main main: PUSHL %EBP MOVL %ESP, %EBP SUBL $24,%ESP # aa, bb, dd e variabile di lavoro di tipo due # ... LEAL -24(%EBP), %EAX # indirizzo risultato, & variabile lavoro PUSHL -8(%EBP) # bb PUSHL -4(%EBP) # aa PUSHL %EAX CALL fun ADDL $8,%ESP MOVL -24(%EBP), %EAX # lavoro.n MOVL %EAX, -16(%EBP) # dd.n MOVL -20(%EBP), %EAX # lavoro.nn MOVL %EAX, -12(%EBP) # dd.nn XORL %EAX, %EAX LEAVE RET Ottimizzazione possibile (consentita): trasmettere come indirizzo del risultato quello della variabile locale dd (-16(%EBP)). G. Frosini Corrispondenza C++ Assembler Slide 38
G. Frosini Corrispondenza C++ Assembler Slide 39 Riferimenti del C++ Riferimento: non è un oggetto; viene implementato con un puntatore costante nascosto (che invece è un oggetto): nome del puntatore: attribuito dal Compilatore; valore del puntatore: il riferimento stesso (che è un indirizzo). Parametri riferimento: nome non noto al programmatore, ma attribuito dal Compilatore (%ebp+8,, %ebp+12 … ); Sottoprogramma: l'indirizzo dell'oggetto riferito viene determinato dalla dereferenziazione del puntatore che implementa il riferimento. G. Frosini Corrispondenza C++ Assembler Slide 39
Implementazione dei parametri riferimento (1) extern "C" void scambia (int& ra, int& rb) { int c; c = ra; ra = rb; rb = c; } G. Frosini Corrispondenza C++ Assembler Slide 40
Implementazione dei parametri riferimento (2) scambia: # ra è il contenuto di 8(%EBP), rb è il contenuto di 12(%EBP), c vale -4(%EBP) PUSHL %EBP # prologo MOVL %ESP, %EBP SUBL $4, %ESP PUSHL %EAX PUSHL %EBX MOVL 8(%EBP), %EAX # c = ra MOVL (%EAX), %EAX MOVL %EAX, -4(%EBP) MOVL 12(%EBP), %EAX # ra = rb MOVL 8(%EBP), %EBX MOVL %EAX, (%EBX) MOVL -4(%EBP), %EAX # rb = c MOVL 12(%EBP), %EBX POPL %EBX POPL %EAX LEAVE # epilogo RET G. Frosini Corrispondenza C++ Assembler Slide 41
Implementazione dei parametri riferimento (3) Tutto avviene come se: i parametri formali fossero esplicitamente dei puntatori; nel corpo della funzione, i riferimenti corrispondessero a puntatori dereferenziati. Sottoprogramma precedente: viene implementato come il seguente: void function scambia (int* pa, int * pb) { int c; c = *pa; *pa =*pb; *pb = c;} Versione con i riferimenti: i due riferimenti (indirizzi) ra ed rb sono costituiti dai contenuti dei puntatori costanti nascosti di indirizzo 12(%EBP) e 8(%EBP). Versione con i puntatori: i due puntatori pa e pb corrispondono agli indirizzi 12(%EBP) e 8(%EBP). G. Frosini Corrispondenza C++ Assembler Slide 42
Programma codifica6 (parametri e variabili locali) (1) // file principale codifica6a.cpp using namespace std; #include <iostream> extern "C" void esamina(char aa, char bb[]); int main() { int i; char cc; char kappa[8]; for(; ;) { cin.get(cc); if (cc == '\n') break; cout << cc << " "; esamina(cc, kappa); for (i=0; i<8; i++) cout << kappa[i]; cout << endl; } return 0; G. Frosini Corrispondenza C++ Assembler Slide 43
Programma codifica6 (parametri e variabili locali) (2) // file secondario codifica6b.cpp extern "C" void esamina(char aa, char bb[]) { int i; for (i=0; i<8; i++) { if ((aa & 0x80) == 0) bb[i] = '0'; else bb[i] = '1'; aa = aa<<1; } G. Frosini Corrispondenza C++ Assembler Slide 44
Programma codifica7 (parametri e variabili locali) (1) # file principale codifica7a.s .EXTERN esamina .TEXT .INCLUDE "servizio.s" .GLOBAL main main: PUSHL %EBP # prologo MOVL %ESP, %EBP SUBL $16, %ESP # variabili locali i, cc, kappa PUSHL %ESI ancora: CALL leggisuccessivo # prelievo carattere MOVB %AL, -8(%EBP) # cc CMPB $'\n', -8(%EBP) # nuova linea JE fine MOVL -8(%EBP), %EAX CALL scrivicarattere # invio del carattere CALL scrivispazio LEAL -16(%EBP), %ESI # &kappa[0] G. Frosini Corrispondenza C++ Assembler Slide 45
Programma codifica7 (parametri e variabili locali) (2) PUSHL %ESI PUSHL -8(%EBP) # cc CALL esamina # sottoprogramma esterno ADDL $8, %ESP MOVL $0, -4(%EBP) # i ripeti: MOVL -4(%EBP), %ESI MOVB -16(%EBP, %ESI), %AL # kappa[i] CALL scrivicarattere INCL -4(%EBP) CMPL $8, -4(%EBP) JB ripeti CALL nuovalinea JMP ancora fine: POP %ESI XORL %EAX, %EAX LEAVE RET G. Frosini Corrispondenza C++ Assembler Slide 46
Programma codifica7 (parametri e variabili locali) (3) # file secondario codifica7b.s .TEXT .GLOBAL esamina esamina: PUSHL %EBP # prologo MOVL %ESP, %EBP SUBL $4, %ESP # variabile locale i PUSHL %EAX PUSHL %EBX PUSHL %ESI MOVB 8(%EBP), %AL # I parametro MOVL 12(%EBP), %EBX # II parametro MOVL $0, -4(%EBP) # i ciclo: MOVL -4(%EBP), %ESI TESTB $0X80, %AL G. Frosini Corrispondenza C++ Assembler Slide 47
Programma codifica7 (parametri e variabili locali) (4) JZ zero MOVB $'1', (%EBX, %ESI) JMP avanti zero: MOVB $'0', (%EBX, %ESI) avanti: SHLB $1, %AL INCL -4(%EBP) CMPL $8, -4(%EBP) JB ciclo POPL %ESI POPL %EBX POPL %EAX LEAVE # epilogo RET G. Frosini Corrispondenza C++ Assembler Slide 48
Programmi Codifica con parametri e variabili locali Programmi codifica6 e codifica7: vengono sviluppati ed eseguiti con i comandi: g++ -m32 codifica6a.cpp codifica6b.cpp –o codifica6 ./codifica6 g++ -m32 codifica7a.s codifica7b.s –o codifica7 ./codifica7 Si possono sviluppare ed eseguire altri due programmi, codifica8 e codifica9 (scritti parte in C++ e parte in Assembler) con i comandi: g++ -m32 codifica6a.cpp codifica7b.s -o codifica8 ./codifica8 g++ -m32 codifica7a.s codifica6b.cpp-o codifica9 ./codifica9 G. Frosini Corrispondenza C++ Assembler Slide 49