Oversikt Kodegenerering Variable Setninger Uttrykk While-setningen

Like dokumenter
Oversikt Kodegenerering Variable Setninger Uttrykk While-setningen

Oversikt Kodegenerering Variable Setninger Uttrykk While-setningen

Oversikt Kodegenerering Variabler Setninger Uttrykk While-setningen

Oversikt Kodegenerering Variable Setninger Uttrykk While-setningen Oppsummering

Dagens tema: Maskinkode. Litt datamaskinhistorie Hva er maskin- og assemblerkode? x86-prosessoren Programkode og variabler

2 Parser. 1 Skanner. 4 Kodegenerator. 3 Sjekker. Oversikt Datamaskinhistorie x86 Kodegenerering Setninger Uttrykk.

Oversikt Deklarasjoner Typesjekk Programmering Datamaskinhistorie x86 Kodegenerering

Dagens tema: Semantisk sjekking. Maskinkode. Hvordan finne deklarasjoner? Hvordan programmere sjekking av riktig navnebruk?

Kompilering Statiske Syntaksanalyse Feilsjekking Eksempel Oppsummering

Oversikt Kompilering Syntaksanalyse Java Feilsjekking Oppsummering

Tema for siste forelesning:

Kompilering Statiske Syntaksanalyse Feilsjekking Eksempel Oppsummering

Oversikt Deklarasjoner Typesjekk Datamaskinhistorie x86 Kodegenerering

Dagens tema: Formålet. Kodegenerering NB! Introduksjon Modulen Code. Enkle variable Noen enkle setninger Uttrykk

Oversikt Oversettelse Logging Implementasjon Oppsummering

Dagens tema: Formålet. Kodegenerering NB! Introduksjon Modulen Code. Enkle variable Noen enkle setninger Uttrykk

Tema for siste forelesning:

Dagens tema: Mer av det dere trenger til del 1

Tema for siste forelesning:

Dagens tema: Mer av det dere trenger til del 1

Det viktigste i en moderne datamaskin er hovedkortet («motherboard»):

Hovedansvarlig. Symbolgenerator. Tregenerator. Litt mer kompliserte setninger med betingelser

En oppsummering (og litt som står igjen)

Dagens tema: Kodegenerering. Versjonskontroll. Variabler, spesielt vektorer Funksjoner, kall og parametre Noen siste gode råd.

Dagens tema. Hva er kompilering? Anta at vi lager dette lille programmet doble.rusc (kalt kildekoden): Hva er kompilering?

Tema for siste forelesning:

Dagens tema: Sjekking

Oppbygningen av en datamaskin Det viktigste i en moderne datamaskin er hovedkortet («motherboard»):

Det viktigste i en moderne datamaskin er hovedkortet («motherboard»):

Dagens tema. Hva er kompilering? Anta at vi lager dette lille programmet (kalt kildekoden): Hva er kompilering?

Notater: INF2270 Assembler

Dagens tema: Resten av det dere trenger til del 1

Det viktigste i en moderne datamaskin er hovedkortet («motherboard»):

UNIVERSITETET I OSLO

Den siste dagen. Pensumoversikt Hovedtanker i kurset Selvmodifiserende kode Overflyt Veien videre... Eksamen

Dagens tema: Resten av det dere trenger til del 1

INF2100. Oppgaver 23. og 24. september 2010

INF2100. Oppgaver uke 40 og

Pensum Hovedtanker Selvmodifiserende Overflyt Veien videre Eksamen. Oppsummering

C og kompilatoren hans. Kompendium for INF2100

Del 3: Evaluere uttrykk

INF2100. Oppgaver 9. oktober 2012 C 100 X 10

Å løse eksamensoppgaver

Dagens tema Programmering av x86 Flytting av data Endring av størrelse

Kort om meg. INF1000 Uke 2. Oversikt. Repetisjon - Introduksjon

INF2100. Oppgaver 6. og 11. oktober 2011 C 100 X 10

En oppsummering. Pensumoversikt Hovedtanker i kurset Selvmodifiserende kode Overflyt Eksamen. Programmeringsoppgaver Flervalgsoppgaver

INF 1000 høsten 2011 Uke september

INF1000 undervisningen INF 1000 høsten 2011 Uke september

Dagens tema. Minnestrukturen Grovt sett ser minnet for hver process slik ut: Flytting av data. Programmering av x86

Intro Rask kode x86-op Optimalisering Inline-kode Konklusjon

INF2100. Oppgave 1. Oppgave 2 4. Løsningsforslag til oppgaver uke 40 og Se figur 1 på neste side.

Dagens tema: 12 gode råd for en kompilatorskriver

Hvordan en prosessor arbeider, del 1

Dagens tema INF1070. Makroer. Sanntidsprogrammering. Avbrudd. Bruker- og supermodus. Blanding av C og assemblerkode. Selvmodifiserende kode

Oversikt. INF1000 Uke 2. Repetisjon - Program. Repetisjon - Introduksjon

Dagens tema. Raskere kode [REB&DRO H kap 5]

Dagens tema: 12 gode råd for en kompilatorskriver. Prosjektet. Modifikasjon av grammatikken. Utifra dette RusC programmet:

Dagens tema. Makroer Ofte gjentar man kodelinjer når man skriver assemblerkode. Da kan det lønne seg å definere en makro:

Løsningsforslag til eksamen i INF2270

Dagens tema: Sjekking (obligatorisk oppgave 3)

LITT OM OPPLEGGET. INF1000 EKSTRATILBUD Stoff fra uke September 2012 Siri Moe Jensen EKSEMPLER

Dagens tema INF2270. Flyt tall (B&O H boken 2.2.3) Hvordan lagres de? Hvordan regner man med dem? Overflyt (B&O H boken )

Dagens tema INF1070. Bit fikling. Makroer. Blanding av C og assemblerkode. Mer om Core War. Dag Langmyhr,Ifi,UiO: Forelesning 22. mai 2006 Ark 1 av 25

Dagens tema: 12 gode råd for en kompilatorskriver. Prosjektet. Koblingen mellom grammatikken og klasser. Utifra dette RusC-programmet:

Intro Evaluering Rask kode x86-op Optimalisering Inline-kode

Dagens tema. Representasjon av mantissen En desimalbrøk: 1 1, INF1070 INF1070 INF1070 INF1070

INF april, 2015 Stein Krogdahl Ifi, UiO. Svar på oppgaver til kap. 8. Ble lagt ut 24. april

Dagens tema: 12 gode råd for en kompilatorskriver. Sjekking av navn. Lagring av navn. Hvordan finne et navn?

INF2100. Oppgave 1, 2 og 3. Løsningsforslag til oppgaver 23. og 24. september Her er det mange mulige løsninger her er én: import java.io.

AlboC og kompilatoren hans. Kompendium for INF2100

Hva er verdien til variabelen j etter at følgende kode er utført? int i, j; i = 5; j = 10; while ( i < j ) { i = i + 2; j = j - 1; }

Nybegynnerkurs i C. Øyvind Grønnesby. 14. oktober Introduksjon Typer Operatorer Kontrollstrukturer Pekere Makroer Lenker

Oversikt. INF1000 Uke 1 time 2. Repetisjon - Introduksjon. Repetisjon - Program

UNIVERSITETET I OSLO

Velkommen til INF2100

Dagens tema. Er maskinen big endian? Denne funksjonen tester det: INF1070 INF1070 INF1070 INF1070

UNIVERSITETET I OSLO

Del 1 En oversikt over C-programmering

MAT-INF 1100: Obligatorisk oppgave 1

Eivind Gard Lund. 24. Mars 2009 Foilene bygger på 2009 utgaven av Andreas Svendsen

INF Noen oppgaver til kap. 8

Dagens tema. Funksjonskall. Flyt-tall. Rekursive kall Lokale variable. Hvordan lagres de? Hvordan regner man med dem?

INF Noen oppgaver til kap. 8

Intro Digital eksamen Rask kode x86-op Optimalisering Inline-kode Konklusjon

Dagens tema. Raskere kode [REB&DRO H kap 5]

INF april, 2014 Stein Krogdahl Ifi, UiO. Svar på oppgaver til kap. 8

INF Repetisjon: Hvordan bygge treet og analysere? 8. september Typisk situasjon. De problematiske syntaks-diagrammene

Forhistorien Menneskene har alltid prøvd å lage maskiner for å løse sine problemer. Dagens tema

Datamaskinenes historie Når, hvor og hvorfor ble de første datamaskiner laget? Hvordan har utviklingen gått? Hva inneholder en datamaskin?

Del 4 Noen spesielle C-elementer

public static <returtype> navn_til_prosedyre(<parameter liste>) { // implementasjon av prosedyren

MAT-INF 1100: Obligatorisk oppgave 1

Dagens tema INF2270. Flyt-tall (B&O H-boken 2.4, 3.14) Hvordan lagres de? Hvordan regner man med dem? Bit-fikling (B&O H-boken 2.1.

UNIVERSITETET I OSLO

IN2030. Oppgave 1. Løsningsforslag. Uke (Disse filene finnes også i mappen ~inf2100/e/e2/.)

Dagens tema. Programmering av x86 INF2270. Minnestrukturen i en prosess. Flytting av data Endring av størrelse. Aritmeriske operasjoner Flagg

Bakgrunnen for INF2100. Velkommen til INF2100. Prosjektet. Hva gjør en kompilator?

INF Oblig 2 semantikksjekk og kodegenerering

Transkript:

Dagens tema Dagens tema: Kodegenerering Introduksjon Enkle variable Uttrykk Tilordning Litt mer kompliserte setninger med betingelser (Alt om kodegenerering unntatt funksjoner.)

Prosjektoversikt Del 0 Del 1 Del 2 f.cflat cflat f.s types chargenerator scanner syntax code error log f.log

Det endelige målet Formålet Vårt oppdrag er å lage en kompilator: Inndata er trerepresentasjonen av C -programmet laget i del 1. Utdata er en fil med x86 assemblerkode. Cb-program x = x+1; Kompilator cflat Assemblerkode addl $1,%eax Assembler gcc Maskinkode 81 01 00 00...

Oversikt Kodegenerering Variable Setninger Uttrykk While-setningen Hvordan ser datamaskinen vår ut? Datamaskinen vår Minnet inneholder tre former for data: Data inneholder globale variabler. Stakken inneholder parametre og lokale variabler. Koden er programmet (som tall).

Hvordan ser datamaskinen vår ut? movl v 1, v 2 Flytt v 1 til v 2. cdq Omform 32-bits %EAX til 64-bits %EDX:%EAX. leal v 1, v 2 Flytt adressen til v 1 til v 2. pushl v Legg v på stakken. popl v Fjern toppen av stakken og legg verdien i v. addl v 1, v 2 Addér v 1 til v 2. subl v 1, v 2 Subtraher v 1 fra v 2. imull v 1, v 2 Multipliser v 1 med v 2. idivl v Del %EDX:%EAX med v ; svar i %EAX. call lab Kall funksjonen i lab. enter $ n,$0 Opprett n byte lokale variabler. ret Returner fra funksjonen. leave Fjern lokale variabler cmpl v 1, v 2 Sammenligning v 1 og v 2. jmp lab Hopp til lab. sete v Sett v =1 om =, ellers v =0. setne v Sett v =1 om, ellers v =0. setl v Sett v =1 om <, ellers v =0. setle v Sett v =1 om, ellers v =0. setg v Sett v =1 om >, ellers v =0. setge v Sett v =1 om, ellers v =0.

Hvordan ser datamaskinen vår ut? faddp Adder to flyttall. fdivp Divider ett flyttall på et annet. fildl v Legg heltall i v på stakken som flyttall. fistpl v Lagre flyttall som int i v. fldl fv Legg flyttall på stakken. fldz Legg 0,0 på stakken. fmulp Multipliser to flyttall. fstpl fv Lagre flyttall som double i fv. fstps fv Lagre flyttall som float i fv. fsubp Subtraher ett flyttall fra et annet.

Et eksempel Anta at vi har C -koden v = 1 + 2; Disse x86-instruksjonene gjør dette: movl $1,%eax # %EAX=1 %ECX=? stack=... pushl %eax # %EAX=1 %ECX=? stack=... 1 movl $2,%eax # %EAX=2 %ECX=? stack=... 1 movl %eax,%ecx # %EAX=2 %ECX=2 stack=... 1 popl %eax # %EAX=1 %ECX=2 stack=... addl %ecx,%eax # %EAX=3 %ECX=2 stack=... movl %eax,v # v = 3

Et eksempel Anta at vi har C -koden v = 1 + 2; Disse x86-instruksjonene gjør dette: movl $1,%eax # %EAX=1 %ECX=? stack=... pushl %eax # %EAX=1 %ECX=? stack=... 1 movl $2,%eax # %EAX=2 %ECX=? stack=... 1 movl %eax,%ecx # %EAX=2 %ECX=2 stack=... 1 popl %eax # %EAX=1 %ECX=2 stack=... addl %ecx,%eax # %EAX=3 %ECX=2 stack=... movl %eax,v # v = 3 Husk! Det finnes mange mulige kodebiter som gjør det samme. I kompendiet står angitt nøyaktig hvilke som skal brukes.

Metoden gencode Hvordan implementere kodegenerering Det beste er å følge samme opplegg som for å sjekke programkoden: Kodegenerering Legg en metode gencode inn i alle klasser som representerer en del av C -programmet (dvs er subklasse av SyntaxUnit).

Metoden gencode class WhileStatm extends Statement { Expression test; StatmList body; @Override void check(decllist curdecls) {. @Override void gencode(funcdecl curfunc) {. static WhileStatm parse() {. @Override void printtree() {.

Konvensjoner Konvensjoner Kodegenerering blir mye enklere om vi setter opp noen fornuftige konvensjoner:

Konvensjoner Konvensjoner Kodegenerering blir mye enklere om vi setter opp noen fornuftige konvensjoner: Alle int-beregninger skal ende opp i %EAX.

Konvensjoner Konvensjoner Kodegenerering blir mye enklere om vi setter opp noen fornuftige konvensjoner: Alle int-beregninger skal ende opp i %EAX. Alle double-beregninger skal legges på flyttallsstakken.

Konvensjoner Konvensjoner Kodegenerering blir mye enklere om vi setter opp noen fornuftige konvensjoner: Alle int-beregninger skal ende opp i %EAX. Alle double-beregninger skal legges på flyttallsstakken. %ECX og %EDX er hjelperegistre.

Konvensjoner Konvensjoner Kodegenerering blir mye enklere om vi setter opp noen fornuftige konvensjoner: Alle int-beregninger skal ende opp i %EAX. Alle double-beregninger skal legges på flyttallsstakken. %ECX og %EDX er hjelperegistre. Hovedstakken (aksessert via %ESP) er til

Konvensjoner Konvensjoner Kodegenerering blir mye enklere om vi setter opp noen fornuftige konvensjoner: Alle int-beregninger skal ende opp i %EAX. Alle double-beregninger skal legges på flyttallsstakken. %ECX og %EDX er hjelperegistre. Hovedstakken (aksessert via %ESP) er til mellomresultater av int-verdier

Konvensjoner Konvensjoner Kodegenerering blir mye enklere om vi setter opp noen fornuftige konvensjoner: Alle int-beregninger skal ende opp i %EAX. Alle double-beregninger skal legges på flyttallsstakken. %ECX og %EDX er hjelperegistre. Hovedstakken (aksessert via %ESP) er til mellomresultater av int-verdier funksjonskall (neste uke)

Konvensjoner Konvensjoner Kodegenerering blir mye enklere om vi setter opp noen fornuftige konvensjoner: Alle int-beregninger skal ende opp i %EAX. Alle double-beregninger skal legges på flyttallsstakken. %ECX og %EDX er hjelperegistre. Hovedstakken (aksessert via %ESP) er til mellomresultater av int-verdier funksjonskall Flyttallsstakken er til (neste uke)

Konvensjoner Konvensjoner Kodegenerering blir mye enklere om vi setter opp noen fornuftige konvensjoner: Alle int-beregninger skal ende opp i %EAX. Alle double-beregninger skal legges på flyttallsstakken. %ECX og %EDX er hjelperegistre. Hovedstakken (aksessert via %ESP) er til mellomresultater av int-verdier funksjonskall Flyttallsstakken er til mellomresultater av double-verdier (neste uke)

Hva slags variabler har vi? Variabler Det finnes fem sorter variabler i C : Enkle Array-er Globale Lokale (De blå tar vi neste uke.) Parametre

Hva slags variabler har vi? Variabler Det finnes fem sorter variabler i C : Enkle Array-er Globale Lokale (De blå tar vi neste uke.) Parametre De kan være int eller double.

Hva slags variabler har vi? Variabler Det finnes fem sorter variabler i C : Enkle Array-er Globale Lokale (De blå tar vi neste uke.) Parametre De kan være int eller double. De kan forekomme i tre ulike situasjoner: Deklarasjon int v; Tilordning v = 1; Bruk if (v>0)...

Generering av globale variable abstract class Declaration extends SyntaxUnit { String name, assemblername; Type type; boolean visible = false; Declaration nextdecl = null;. abstract class VarDecl extends Declaration {. class GlobalSimpleVarDecl extends VarDecl { GlobalSimpleVarDecl(String n) { super(n); assemblername = (Cflat.underscoredGlobals()? "_" : "") + n; @Override void gencode(funcdecl curfunc) { Code.genVar(assemblerName, true, declsize(), type.typename()+" "+name+";");.

Generering av globale variable Metoden Code.genVar vil sette av plass til globale variabler: public static void genvar(string name, boolean global, int nbytes, String comment) { if (! generatingdata) { codefile.println(".data"); generatingdata = true; if (global) codefile.println(".globl " + name); printlabel(name, false); codefile.printf(".fill %-24d", nbytes); if (comment.length() > 0) { codefile.print("# " + comment); codefile.println();

Tilordning Setninger I kompendiet finner vi kodeskjemaer for alle setningene. Assignment iv = ie ia [ ie 1 ] = ie 2 ; Beregn ie med svar i %EAX movl %eax, iv Beregn ie 1 med svar i %EAX pushl %eax Beregn ie 2 med svar i %EAX leal ia,%edx popl %ecx movl %eax,(%edx,%ecx,4)

Tilordning Assignment av flyttall fv = fe Beregn fe med svar på f-stakken fstpl fv

Tilordning Assignment av flyttall fv = fe Beregn fe med svar på f-stakken fstpl fv Noen ganger må vi konvertere fra int til float: fv = ie ; Beregn ie med svar i %EAX movl %eax,.tmp fildl.tmp fstpl fv (Legg merke til hjelpevariabelen.tmp den må alltid være der.)

Tilordning Et forslag til implementering: class AssignStatm extends Statement { Assignment assignment; @Override void gencode(funcdecl curfunc) { assignment.gencode(curfunc);. class Assignment extends SyntaxUnit { Variable lhs; /* "Left hand side" */ Expression rhs; /* "Right hand side" */ @Override void gencode(funcdecl curfunc) { if ( det dreier seg om et array-element ) { // To be written... else { rhs.gencode(curfunc); lhs.declref.genstore(rhs.valtype);.

Tilordning Hint Alle VarDecl bør ha en genstore- og genstorearray-metode for å lage kode for tilordning til seg selv; de kan se slik ut: abstract class VarDecl extends Declaration { VarDecl(String n) { super(n); void genstore(type valtype) { if (type==types.doubletype && valtype==types.doubletype) { Code.genInstr("", "fstpl", assemblername, name+" ="); else if (type==types.doubletype && valtype==types.inttype) { Code.genInstr("", "movl", "%eax,"+code.tmplabel, ""); Code.genInstr("", "fildl", Code.tmpLabel, " (double)"); Code.genInstr("", "fstpl", assemblername, name+" ="); else if (type==types.inttype && valtype==types.doubletype) { Code.genInstr("", "fistpl", assemblername, name+" = (int)"); else if (type==types.inttype && valtype==types.inttype) { Code.genInstr("", "movl", "%eax,"+assemblername, name+" ="); else { Error.panic("Declaration.genStore");

Hvordan lagres uttrykk? Uttrykk Hvordan lager vi kode for et uttrykk som expression term 4 * a - 17 factor factor -? number 4 variable a * number 17

Operander Operander Det er ganske enkelt å lage kode som legger en global enkel int-variabel i %EAX-registeret eller en double-variabel på flyttallsstakken: iv movl iv,%eax fv fldl fv

Operander Operander Det er ganske enkelt å lage kode som legger en global enkel int-variabel i %EAX-registeret eller en double-variabel på flyttallsstakken: iv movl iv,%eax fv fldl fv Det er like enkelt for int-konstanter (tall eller tegn). n movl $ n,%eax ($-tegnet angir at det er snakk om en tallkonstant.)

Operatorer Aritmetisk int-operatorer ie 1 + ie 2 Beregn ie 1 med svar i %EAX pushl %eax Beregn ie 2 med svar i %EAX movl %eax,%ecx popl %eax addl %ecx,%eax

Operatorer Aritmetisk int-operatorer ie 1 + ie 2 Beregn ie 1 med svar i %EAX pushl %eax Beregn ie 2 med svar i %EAX movl %eax,%ecx popl %eax addl %ecx,%eax Ved at alle int-operander er innom %EAX blir det enklere å skrive kodegenereringen.

Operatorer Aritmetisk int-operatorer ie 1 + ie 2 Beregn ie 1 med svar i %EAX pushl %eax Beregn ie 2 med svar i %EAX movl %eax,%ecx popl %eax addl %ecx,%eax Ved at alle int-operander er innom %EAX blir det enklere å skrive kodegenereringen. Divisjon og sammenligninger er litt vanskeligere; se tabellene i kompendiet.

Operatorer Aritmetisk int-operatorer ie 1 + ie 2 Beregn ie 1 med svar i %EAX pushl %eax Beregn ie 2 med svar i %EAX movl %eax,%ecx popl %eax addl %ecx,%eax Ved at alle int-operander er innom %EAX blir det enklere å skrive kodegenereringen. Divisjon og sammenligninger er litt vanskeligere; se tabellene i kompendiet. Hvorfor må ie 1 legges på stakken?

Operatorer Aritmetisk int-operatorer ie 1 + ie 2 Beregn ie 1 med svar i %EAX pushl %eax Beregn ie 2 med svar i %EAX movl %eax,%ecx popl %eax addl %ecx,%eax Ved at alle int-operander er innom %EAX blir det enklere å skrive kodegenereringen. Divisjon og sammenligninger er litt vanskeligere; se tabellene i kompendiet. Hvorfor må ie 1 legges på stakken? double-operatorene fordrer helt annen kode.

Kodegenering While-setningen med int-test while ( ie ) { S.Ln 1 :.Ln 2 : Beregn ie med svar i %EAX cmpl $0,%eax je.ln 2 S jmp.ln 1

Kodegenering While-setningen med double-test while ( fe ) { S.Ln 1 :.Ln 2 : Beregn fe med svar på f-stak fstps.tmp cmpl $0,.tmp je.ln 2 S jmp.ln 1

Kodegenering Siden de to variantene er like med unntak av kode for testen, er det nyttig med public abstract class Type { public abstract int size(); public abstract String typename(); public void genjumpifzero(string jumplabel) { public class Types { public static BasicType doubletype, inttype; public static void init() { doubletype = new BasicType() { ; @Override public void genjumpifzero(string jumplabel) { Code.genInstr("", "fstps", Code.tmpLabel, ""); Code.genInstr("", "cmpl", "$0,"+Code.tmpLabel, ""); Code.genInstr("", "je", jumplabel, "");

Navnelapper Lokale navnelapper Når vi skal lage slike hopp, trenger vi stadig nye navnelapper. Dette kan vi få fra Code-modulen: private static int numlabels = 0; public static String getlocallabel() { return String.format(".L%04d", ++numlabels);

Komplett kode Hele koden for WhileStatm class WhileStatm extends Statement { Expression test; StatmList body; @Override void gencode(funcdecl curfunc) { String testlabel = Code.getLocalLabel(), endlabel = Code.getLocalLabel(); Code.genInstr(testLabel, "", "", "Start while-statement"); test.gencode(curfunc); test.valtype.genjumpifzero(endlabel); body.gencode(curfunc); Code.genInstr("", "jmp", testlabel, ""); Code.genInstr(endLabel, "", "", "End while-statement");

Et eksempel while (a < 10) { a = a + 1;.L0001: # Start while-statement movl a,%eax # a pushl %eax movl $10,%eax # 10 popl %ecx cmpl %eax,%ecx movl $0,%eax setl %al # Test < cmpl $0,%eax je.l0002 movl a,%eax # a pushl %eax movl $1,%eax # 1 movl %eax,%ecx popl %eax addl %ecx,%eax # Compute + movl %eax,a # a = jmp.l0001.l0002: # End while-statement