ASM: catena di compilazione



Documenti analoghi

Laboratorio di Programmazione 1. Docente: dr. Damiano Macedonio Lezione 18 31/03/2014

FASE DEBUGGING: Compiler Linker. controllando che la voce Genera le informazioni per il debug cioè. "Generate debugging information"

ToolChain: Come Generare Applicazioni in Linguaggio Macchina

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

Linguaggio C. Fondamenti. Struttura di un programma.

Codifica: dal diagramma a blocchi al linguaggio C++

Compilatore risorse display grafico LCD serie IEC-line

NOZIONI BASE PER ESERCITAZIONI

Introduzione alla programmazione in C

Concetto di Funzione e Procedura METODI in Java

AXO Architettura dei Calcolatori e Sistema Operativo. processo di assemblaggio

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

Allocazione dinamica della memoria - riepilogo

Funzioni in C. Violetta Lonati

Linguaggi di programmazione

Introduzione al Linguaggio C

Hardware di un Computer

Il simulatore SPIM SPIM

GHPPEditor è un software realizzato per produrre in modo rapido e guidato un part program per controlli numerici Heidenhain.

Programmare in Java. Olga Scotti

COS È UN LINGUAGGIO? LINGUAGGI DI ALTO LIVELLO LA NOZIONE DI LINGUAGGIO LINGUAGGIO & PROGRAMMA

Introduzione a Dev-C++

Calcolatori Elettronici Parte X: l'assemblatore as88

MIPS Instruction Set 2

Registratori di Cassa

Introduzione a GCC: GNU Compiler Collection

Sistema operativo: Gestione della memoria

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};

Gian Luca Marcialis studio degli algoritmi programma linguaggi LINGUAGGIO C

Università di Roma Tor Vergata Corso di Laurea triennale in Informatica Sistemi operativi e reti A.A Pietro Frasca.

SISTEMI OPERATIVI. Prof. Enrico Terrone A. S: 2008/09

Dall Algoritmo al Programma. Prof. Francesco Accarino IIS Altiero Spinelli Sesto San Giovanni

Approccio stratificato

Corso di Informatica

Manuale Operativo per l utilizzo della piattaforma E-Learning@AQ. Versione 1.1

EDICOLA MANAGER EM Importer

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

Fasi di creazione di un programma

INSTALLAZIONE NUOVO CLIENT TUTTOTEL (04 Novembre 2014)

Guida all uso dell ambiente di sviluppo 1 integrato o IDE. JCreator LE 4.50

Tipi primitivi. Ad esempio, il codice seguente dichiara una variabile di tipo intero, le assegna il valore 5 e stampa a schermo il suo contenuto:

GUIDA ALLA PROGRAMMAZIONE GRAFICA IN C

Fondamenti di Informatica e Laboratorio T-AB T-16 Progetti su più file. Funzioni come parametro. Parametri del main

Tutorial per l installazione del J2SE 6 e configurazione del sistema operativo

Fondamenti di Informatica Ingegneria Clinica Lezione 19/10/2009. Prof. Raffaele Nicolussi

Ing. Paolo Domenici PREFAZIONE

Modulo 4 Il pannello amministrativo dell'hosting e il database per Wordpress

Istruzioni per l installazione del software per gli esami ICoNExam (Aggiornate al 15/01/2014)

Il calendario di Windows Vista

Per chi ha la Virtual Machine: avviare Grass da terminale, andando su Applicazioni Accessori Terminale e scrivere grass

Siamo così arrivati all aritmetica modulare, ma anche a individuare alcuni aspetti di come funziona l aritmetica del calcolatore come vedremo.

Programmazione C Massimo Callisto De Donato massimo.callisto@unicam.it

Office 2007 Lezione 08

ISTRUZIONI PER L INSTALLAZIONE DI MINGW

System Center Virtual Machine Manager Library Management

ELENCO CLIENTI FORNITORI Patch1

Sistemi Operativi MECCANISMI E POLITICHE DI PROTEZIONE. D. Talia - UNICAL. Sistemi Operativi 13.1

MECCANISMI E POLITICHE DI PROTEZIONE 13.1

STAMPA UNIONE DI WORD

Convertitori numerici in Excel

Mac Application Manager 1.3 (SOLO PER TIGER)

Calcolatori Elettronici. La memoria gerarchica La memoria virtuale

Ambienti di Sviluppo

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

Il Software e Il Sistema Operativo. Prof. Francesco Accarino IIS Altiero Spinelli A.S. 09/10

Fondamenti di Informatica 1. Prof. B.Buttarazzi A.A. 2010/2011

Lezione 1: L architettura LC-3 Laboratorio di Elementi di Architettura e Sistemi Operativi 10 Marzo 2014

Guida all utilizzo del compilatore lcc-win32 per creare una applicazione console

A intervalli regolari ogni router manda la sua tabella a tutti i vicini, e riceve quelle dei vicini.

puntatori Lab. Calc. AA 2007/08 1

Tale attività non è descritta in questa dispensa

Esercizi su. Funzioni

Introduzione al linguaggio C Gli array

Dynamic Linking. Introduzione Creazione di una libreria dinamica Uso di una libreria dinamica

Tutorial sugli ambienti di sviluppo: Eclipse e NetBeans

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

Gli array. Gli array. Gli array. Classi di memorizzazione per array. Inizializzazione esplicita degli array. Array e puntatori

MANUALE EDICOLA 04.05

INTRODUZIONE AGLI ALGORITMI INTRODUZIONE AGLI ALGORITMI INTRODUZIONE AGLI ALGORITMI INTRODUZIONE AGLI ALGORITMI

EDICOLA MANAGER EM Importer

Dispensa YACC: generalità

Protezione. Protezione. Protezione. Obiettivi della protezione

Prova Finale a.a. 2011/2012. Laboratorio 1: Introduzione a Java e Eclipse

Dispense di Informatica per l ITG Valadier

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

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

Plate Locator Riconoscimento Automatico di Targhe

Il memory manager. Gestione della memoria centrale

Scrivere un programma in Java

Invio SMS. DM Board ICS Invio SMS

SOFTWARE. È l insieme delle istruzioni che è necessario fornire alla macchina per il suo funzionamento. Vi sono due categorie di software:

FPf per Windows 3.1. Guida all uso

Gestione dei File in C

Linguaggi e Paradigmi di Programmazione

Estensione di un servizo di messaggistica per telefonia mobile (per una società di agenti TuCSoN)

Transcript:

ASM: catena di compilazione Lorenzo Dematté October 2, 2011 1 La nostra Macchina Virtuale Una macchina virtuale o modello di programmazione è l ambiente nel quale i programmi girano. Di solito si parla di macchina virtuale solo nel caso di linguaggi interpretati o a bytecode (come a JVM, la macchina virtuale di Java) ma in realtà tutte il software viene programmato facendo delle assunzioni che vanno oltre quelle della macchina fisica sulla quale girano. E il caso del C/C++ per esempio, dal quale ci aspettiamo alcune funzioni standard; o ancora quando programmiamo utility per sistema operativo Linux, dove spesso si segue lo standard POSIX. In questi 2 casi stiamo programmando, per esempio, la VM ANSI C, o ISO C++, o ancora la VM POSIX. Nel nostro caso, programmando in assembly saremo molto vicini alla macchina fisica, ma anche noi faremo delle assunzioni: il set di istruzioni e opcode Intel a 32 bit (chiamto i386, x86, o ancora ia32) 1 ; un modello di memoria a 32 bit flat (come quelli che si trovano nelle varianti a 32 bit di Windows, Linux e OSX). La nostra VM quindi sarà ia32 con modello di memoria FLAT 2. 2 La catena di compilazione La compilazione é il processo di tradurre un programma scritto in un certo linguaggio (il codice sorgente) in un programma equivalente in un altro linguaggio (codice oggetto). Spesso il codice oggetto é codice macchina eseguibile. Quando compiliamo un programma (come esempio, consideriamo un tipico compilatore C), in realtá stiamo facendo una serie di passaggi di cui la compilazione vera e propria é solo uno: preprocessing compilazione assemblaggio linking 1 Stiamo parlando qui di architettura, non di processori: i vari modelli di processori Intel e AMD implementano tutti il set di istruzioni i386, e quelli piu recenti il set esteso x86. Ogni nuovo modello porta con se qualche nuova estensione, ma di poco conto. 2 L architettura ia32 supporta diversi tipi di gestione della memoria virtuale: segmentazione, paginazione, segmentazione paginata. Il modello FLAT prevede un unico segmento, della dimensione massima indirizzabile (32 bit nel nostro caso). 1

Nel preprocessing un singolo file C viene preprocessato, cioé le dichiarazione comincianti con # (#define, #include ecc.) vengono esaminate e sostituite con altro codice. Nella compilazione il codice C viene elaborato e tradotto in codice assembly. Nell assemblaggio, il codice ASM generato viene assemblato, producendo un file oggetto (.o oppure.obj), che contiene codice macchina e tabelle di linking. Durante il linking, un programma detto linker prende l insieme di files oggetto generati, ogni libreria aggiuntiva specificata implicitamente o esplicitamente 3 e li unisce in un unico programma eseguibile, risolvendo le referenze tra i vari files oggetto (tipicamente, chiamate a funzioni). 3 I files oggetto I files oggetto contengono solitamente una tabella di linking, codice macchina e (solo nelle build di debug) simboli di debug. I simboli di debug sono informazioni aggiuntive sui nomi e la locazione nei files sorgenti di funzioni, variabili ecc. Sono quindi una sorta di mappa che permette al debugger di seguire passo passo il codice macchina eseguito e allo stesso tempo mostrare al programmatore variabili e codici in un modo piú leggibile. Ci sono programmi che permettono di visualizzare il contenuto dei file oggetto, come disassamblatori ecc. Per esempio, il tool objdump in ambiente UNIX-like e il tool pedump in Windows. Le tabelle di linking sono usate dal linker per reperire informazioni su dove si trovino e dove ci sia il bisogno di certe funzione. Infatti, ogni file oggetto può usare funzioni definite in un altro file o libreria ed esporre delle funzioni che saranno chiamate da altre librerie o da altri file oggetto. Per esempio: #include <stdio.h> extern int add(int a, int b) { int res; res = a + b; return res; } int main() { int i = 2; int j = 3; } printf("hello %d + %d = %d", i, j, add(i, j)); return i + j; Questo file definisce due funzioni, main and add, e ne usa altre, tra cui printf. printf è dichiarata nel file stdio.h, ma é definita altrove (nella libreria standard 3 La libreria standard del C è un esempio di libraria che viene sempre implicitamente aggiunta; altre librerie sono aggiunte a seconda del sistema operativo (p.e. kernel32.dll sotto Windows) 2

Sections: Idx Name Size VMA LMA File off Algn 0.text 00000090 00000000 00000000 00000104 2**4 CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE 1.data 00000000 00000000 00000000 00000000 2**4 ALLOC, LOAD, DATA 2.bss 00000000 00000000 00000000 00000000 2**4 ALLOC 3.stab 00000a80 00000000 00000000 00000194 2**2 CONTENTS, RELOC, READONLY, DEBUGGING 4.stabstr 00004d45 00000000 00000000 00000c14 2**0 CONTENTS, READONLY, DEBUGGING 5.rdata 00000020 00000000 00000000 00005959 2**4 CONTENTS, ALLOC, LOAD, READONLY, DATA SYMBOL TABLE: [ 0](sec -2)(fl 0x00)(ty 0)(scl 103) (nx 1) 0x00000000 hello.cpp File [ 2](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 1) 0x00000000 Z3addii AUX tagndx 0 ttlsiz 0x0 lnnos 0 next 0 [ 4](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000014 _main [ 5](sec 1)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000.text AUX scnlen 0x84 nreloc 4 nlnno 0 [ 7](sec 2)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000.data AUX scnlen 0x0 nreloc 0 nlnno 0 [ 9](sec 3)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000.bss AUX scnlen 0x0 nreloc 0 nlnno 0 [ 11](sec 4)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000.stab AUX scnlen 0xa80 nreloc 5 nlnno 0 [ 13](sec 5)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000.stabstr AUX scnlen 0x4d45 nreloc 0 nlnno 0 [ 15](sec 6)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000.rdata AUX scnlen 0x13 nreloc 0 nlnno 0 [ 17](sec 0)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000000 main [ 18](sec 0)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000 alloca [ 19](sec 0)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000000 _printf Figure 1: Parte dell output del porgramma objdump. Notate le tabelle di linking. del C). Queste funzioni e informazioni a loro relative sono inserite nelle tabelle di linking (Fig. 1). 4 GCC: GNU Compiler Collection I tools visti a lezione comprendono i compilatori, assemblatore e linker della GNU. Il vantaggio di questi tools è che sono di qualità abbastanza buona e che sono disponibili su praticamente tutte le piattaforme. Gli svantaggi è che non sono di qualità ottima (per quanto riguarda aderenza a standard e qualità del codice prodotto) e che usano una sintassi diversa da quelle ufficiali Intel e AMD per il codice assembly. 3

4.1 Windows Per windows, andremo a usare il porting dei tools GNU dato da cygwin. Quello che é necessario sono le librerie di runtime del C, versione sviluppo, il pacchetto GCC, il pacchetto binutils, e il pacchetto GDB. 4.2 Linux Tutte le distro Linux includono GCC o pacchetti per installarlo. A noi servono le librerie di runtime del C, versione sviluppo, il pacchetto GCC, il pacchetto binutils, e il pacchetto GDB. 4.3 Mac Mac OSX fornisce tutti i tools GNU con il suo pacchetto di sviluppo XCode. Installatelo, oppure se avete una vecchia vesione di OSX considerate MacPorts o Fink (cercate su google). 4.4 Utilizzo Utilizzare i tools é semplice: basta aprire un terminale e lanciare il comando corrispondente: gcc per il compilatore, as per l assembler, ld per il linker. Alcuni switch importanti sono: -g (-gstabs per as) genera i simboli di debugging. NB: va usata su tutti i tools della catena! -o mette l output nel file seguente. -v per il GCC: fa vedere la riga di comando completa dei programmi invocati -E per il GCC: solo preprocessing -S per il GCC: solo preprocessing e generazione codice --save-temps per il GCC: salva i file temporanei (.ii per il file C preprocessato,.s per il codice ASM generato,.o per il file oggetto) Tutti hanno opzioni --help o man pages che spiegano in dettaglio le opzioni. 4.5 Esempio Come esempio, consideriamo una semplice funzione della libreria standard del C: strcpy. La string copy (strcpy) copia una stringa data in input in un altra, usando un buffer pre-allocato dato come input alla funzione. In pratica, la funzione copia carattere per carattere finchè non arriva al terminatore NULL 4 Di seguito, il codice assembler per la funzione: 4 Ricordiamo che una string non é altro che un array di bytes, dove ogni singolo byte é un carattere in codifica ASCII, terminata dal carattere speciale \0 (NULL) che ha il valore di zero. 4

.data src:.string "Hello World" dst:.skip 20.text.globl _start _start: movl $src, %eax movl $dst, %ebx whil: movsbl (%eax), %ecx testl %ecx, %ecx jz exit movb movb addl addl jmp (%eax), %dl %dl, (%ebx) $1, %eax $1, %ebx whil exit: movb $0, (%ebx) Per assemblare questo codice, possiamo invocare il comando gcc (che si occuperá di chiamare l assembler ed il linker nel modo corretto), oppure fare a mano i due passi distinti: as -gstabs -o strcyp.s strcpy.o ld -g -o strcpy strcpy.o A seconda del vostro ambiente di esecuzione (shell + sistema operativo), potrebbe essere necessario rinominare l etichetta globale start in main o main: la bash sotto Linux per esempio richiede che il programma lanciato sia sempre linkato alla libreria standard del C (per settare standard input/output/error, l ambiente, i parametri alla riga di comando, ecc.). In questo caso, il vostro programma comincia dentro la libreria del C, in una funzione che poi va a chiamare la main. E quindi necessario che un simbolo main sia definito nella tabella di linking del nostro file oggetto. Seguite l errore dato da vostro linker per il nome decorato (i.e. con il corretto numero di davanti) da usare nel vostro caso. Se provate a eseguire il programma direttamente, fallirà (segmentation fault sotto Linux, GPE sotto Windows), perché non abbiamo fatto nulla per rendere il nostro programma simpatico al sistema operativo. Un moderno sistema operativo chiede a un programma che viene lanciato di fare una serie di operazioni che noi per semplicità non vediamo 5. Possiamo comunque eseguire il 5 In particolare, il programma alla fine deve chiamare una funzione (es: exit sotto Linux) per informare il SO che la sua esecuzione è finita. Altrimenti, il processore continuerà a 5

programma passo passo in un debugger, ed esaminare i vari registri e variabili per vedere come le varie istuzioni sono eseguite. 5 Assembly inline Un alternativa é quella di inserire una porzione di codice assembler dentro un programma C, in modo da far fare tutte le operazioni di contorno allo scheletro C e di concentrarci sull algoritmo. Questo modo di scrivere codice ASM si chiama assembler inline. Il GCC ha una sintassi molto complicata per l assembler inline; andiamo a vedere come fare nel caso della strcpy: #include <stdio.h> int main() { char* src = "Hello world"; char dst[20]; asm ( "start: movsbl (%0), %%ecx\n\t" "testl %%ecx, %%ecx\n\t" "jz exit\n\t" "movb "movb "addl "addl "jmp (%0), %%dl\n\t" %%dl, (%1)\n\t" $1, %0\n\t" $1, %1\n\t" whil\n\t" "exit: movb $0, (%1)\n\t" : : "r" (src), "r" (dst) : "%ecx", "%edx"); printf("src: %s, dst: %s\n", src, dst); return 0; } Notiamo subito 2 cose: che l assemble é scritto riga per riga come stringa, inclusi i caratteri di fine riga ( \n ); sull assembly che scriviamo vengono fatte alcune sostituzione, e poi viene passato pari pari all assembler. Seconda cosa, i registri vengono prefissti da 2 % (%%ecx, per esempio) e ci sono dei numeri prefissati da %. I primi hanno 2 segni per distinguerli dai secondi, che sono pseudo-registri che verranno sostituiti con registri (o riferimenti a memoria) reali prima di passare il codice all assemblatore. eseguire il programma, caricando come prossima istruzione la parola di memoria presente dopo l ultima istruzione. Chiaramente, essendo dati garbage, la probabilità di ottenere un Segmentation fault o un Invalid Instruction è prossima a 1 6

Cosa viene associato a questi pseudo-registri é definito nelle righe sottostanti che iniziano con : elementi di output: pseudo-registri associati a una variabile. Il valore della variabile alla fine del blocco ASM sará impostato uguale a quello del pseudo-registro. elementi di input: pseudo-registri associati a una variabile. Il valore del registro all inizio del blocco ASM sará impostato uguale a quello della variablile. registri sporcati: lista di registri che abbiamo usato nel nostro blocco. I pseudo registri possono essere di tipo: =r alla variabile verrá dato un registro vero (tra quelli disponibili); la variabile verrá letta e scritta r alla variabile verrá dato un registro vero (tra quelli disponibili); la variabile verrá solo letta m, =m la variabile potrá essere usata dentro al codice come pseudoregistro, ma verrano generati dei riferimenti a memoria. Ci sono molti altri modificatori, e l uso puó diventare complicato. Chi volesse saperne di piú, si riferisca al manuale del GCC. 6 GDB: debugger Vedi appunti lezione e reference card sul sito esse3. 7 La convenzione di chiamata del C (cdecl) Per convenzione di chiamata si intende il contratto che si crea tra codice che chiama la funzione (il chiamante) e la funzione (chiamata). Ovviamente, le due parti si devono mettere d accordo: dove sono memorizzati i valori dei parametri? Dove mettere il valore di ritorno? Quali registri posso sporcare, e quali invece devono rimanere come sono (e, da parte del chiamante, quali registri non posso considerare invariati dopo una chiamata a funzione?) Ci sono molte convenzioni di chiamata; le piu diffuse usano lo stack come luogo principale per lo scambio dei dati. In particolare, per le architetture Intel, c e un registro particolare (EBP) che viene usato per facilitare la creazione e l uso di uno stack frame, una zona dello stack, specifica per ogni funzione, usata per lo scambio di informazioni tra chiamante e chiamato. In particolare, noi ci soffermiamo sulla convenzione di chiamata del C (cdecl): i parametri vengono messi sullo stack dal chiamante, da dx a sx; la f chiamata salva il base pointer del frame precedente, e lo ripristina all uscita; la f chiamata riserva spazio sullo stack per le sue variabili locali; 7

la f puo sporcare solo EAX, ECX, EDX; il valore di ritorno va messo/si trova in EAX la funzione chiamante si occupa di togliere i parametri dallo stack (es: perché?) Figure 2: Lo stack frame nella convenzione di chiamata del C La chiamata si divide in 6 fasi, alternate tra chiamante e fun chiamata: chiamante: passaggio dei parametri, trasferimento controllo, salvataggio punto di ritorno (PUSH, CALL); chiamata: prologo (salva EBP, spazio per i locali con SUB); chiamata: esecuzione; chiamata: epilogo (ripristino ESP, EBP, RET); chiamante: pulizia stack dai parametri (ADD); chiamante: salvataggio valore di ritorno. Questa sequenza di operazioni porta alla realizzazione e distruzione dello stack frame, in Fig. 2, come visto a lezione. 8 Altre convenzioni di chiamata su Intel 8

Figure 3: Lo stack frame nella convenzione di chiamata del C++, per le funzioni membro Figure 4: Lo stack frame nella convenzione di chiamata del C++, per le funzioni virtuali 9