INF-5110 Oppgaver kodegenerering, 7/5-09

Like dokumenter
Avsluttende om kodegenerering: Tilleggsnotat fra AHU Samt: En oversikt over bruk av Javas Byte-kode

Litt om Javas class-filer og byte-kode

NOTAT (pensum!) Javas klasse-filer, byte-kode og utførelse. INF 5110, 10/5-2011, Stein Krogdahl

Javas klasse-filer, byte-kode og utførelse (og litt om C# sin CIL-kode)

NOTAT (pensum!) Javas klasse-filer, byte-kode og utførelse

Kodegenerering del 3: Tilleggsnotat fra AHU Samt litt om class-filer og byte-kode INF5110 V2007. Stein Krogdahl, Ifi UiO

INF-5110 Oppgaver kodegenerering etc. INF-5110, vår 2011

Oppgaver til kodegenerering etc. INF-5110, 12. mai, 2015

Oppgaver til kodegenerering etc. INF-5110, 16. mai, 2014

Generiske mekanismer i statisk typede programmeringsspråk

Mer kodegenerering: Tilleggsnotat fra AHU Om Javas Byte-kode INF april 2009

Kap. 8 del 1 kodegenerering INF5110 Vår2007

Pensumoversikt - kodegenerering. Kap. 8 del 1 kodegenerering INF5110 v2006. Hvordan er instruksjonene i en virkelig CPU? Arne Maus, Ifi UiO

Mer kodegenerering: Tilleggsnotat fra AHU. INF mai Stein Krogdahl,

INF mai 2014 Stein Krogdahl, Ifi, UiO

UNIVERSITETET I OSLO

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

UNIVERSITETET I OSLO

INF og 13. april, Stein Krogdahl, Ifi UiO

INF april, 2015 Kap. 8 kodegenerering. Del 2

Kodegenerering, del 2: Resten av Kap. 8 pluss tilleggsnotat (fra kap. 9 i ASU ) INF5110 V2007

MED SVARFORSLAG UNIVERSITETET I OSLO. Det matematisk-naturvitenskapelige fakultet

Kap. 8 del 1 kodegenerering INF april, 2008

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

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

Dette er foiler til: 1. Tilleggsnotat fra bok av Aho, Sethi og Ullman Notatet legges ut på undervisnings-planen. Beklager dårlig kopi!

Kap. 8 kodegenerering INF april, 2009

UNIVERSITETET I OSLO

INF Noen oppgaver til kap. 8

INF Noen oppgaver til kap. 8

OPPGAVE 1 OBLIGATORISKE OPPGAVER (OBLIG 1) (1) Uten å selv implementere og kjøre koden under, hva skriver koden ut til konsollen?

INF Seminaroppgaver til uke 3

Velkommen til INF5110 Kompilatorteknikk

Velkommen til INF Kompilatorteknikk

Med Svarforslag UNIVERSITETET I OSLO. Det matematisk-naturvitenskapelige fakultet. 3 sider (side 6, 7 og 8, rives ut, fylles ut og leveres)

2 Om statiske variable/konstanter og statiske metoder.

Generiske mekanismer i statisk typede programmeringsspråk INF5110 April, 2009

Stein Krogdahl, Ifi UiO

Tre måter å lese fra terminal. Java 4. Eksempel. Formatert utskrift til skjerm

INF oktober Dagens tema: Uavgjørbarhet. Neste uke: NP-kompletthet

Diverse eksamensgaver

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

Del 4 Noen spesielle C-elementer

Runtimesystemer - II. Funksjoner som parametere. Virtuelle metoder

Runtime-omgivelser Kap 7 - I

Ordliste. Obligatorisk oppgave 1 - Inf 1020

MED SVARFORSLAG UNIVERSITETET I OSLO

Kapittel 1. Datamaskiner og programmeringsspråk. 1.1 Programmering

UNIVERSITETET I OSLO

INF225 høsten 2003 Prosjekt del 4: kodegenerering

3 emner i dag! INF1000 Uke 5. Objekter og pekere. null. Litt om objekter, pekere og null Filer og easyio Litt mer om tekster

INF og 27. april, 2010 Kap. 8 kodegenerering. Stein Krogdahl, Ifi UiO

UNIVERSITETET I OSLO

Introduksjon til DARK assembly

Introduksjon til objektorientert. programmering. Hva skjedde ~1967? Lokale (og globale) helter. Grunnkurs i objektorientert.

Kapittel 1: Datamaskiner og programmeringsspråk

Repetisjon: Statiske språk uten rekursive metoder (C1 og C2) Dagens tema Kjøresystemer (Ghezzi&Jazayeri 2.6, 2.7)

Runtimesystemer Kap 7 - I

Dagens tema Kjøresystemer (Ghezzi&Jazayeri 2.6, 2.7)

2 Om statiske variable/konstanter og statiske metoder.

Velkommen til INF Kompilatorteknikk

UNIVERSITETET I OSLO

Velkommen til INF Kompilatorteknikk

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

Dagens temaer. Fra kapittel 4 i Computer Organisation and Architecture. Kort om hurtigminne (RAM) Organisering av CPU: von Neuman-modellen

Beskrivelse av programmeringsspråket Compila15 INF Kompilatorteknikk Våren 2015

Del 1 En oversikt over C-programmering

Velkommen til INF Kompilatorteknikk

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

Oppgave 1 - Linux kommandolinje (%)

Beskrivelse av programmeringsspråket Simpila INF Kompilatorteknikk Våren 2012

I dag. Rep: Oppsummering - variabler. Rep: Datatyper. INF1000 (Uke 3) Mer om uttrykk, terminal I/O, forgreninger

Oppsummering Assemblerkode Hopp Multiplikasjon Kode og data Array Oppsummering

Læringsmål og pensum. Utvikling av informasjonssystemer. Oversikt. Systemutvikling Systemutvikling i seks faser Femstegs prosedyre for programmering

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

INF mai 2014 Stein Krogdahl, Ifi, UiO

Oversikt. INF1000 Uke 6. Objekter, pekere og null. Lese og skrive fra/til fil. Litt om objekter, pekere og null Filer og easyio. Litt mer om tekster

Repetisjon: høydepunkter fra første del av MA1301-tallteori.

Velkommen til INF Kompilatorteknikk

Løsningsforslag ukeoppg. 9: okt (INF Høst 2011)

Forelesning 9 mandag den 15. september

Oppgave 1 a. INF1020 Algoritmer og datastrukturer. Oppgave 1 b

Forelesning ISA: IJVM Kap 4.2

TOD063 Datastrukturer og algoritmer

2012 2a. C rc; void main() { rc = new C (); rc.m2(); } } INF 3110/ INF /28/13 1

Runtimesystemer Kap 7 - I

Spørsmål fra forrige forelesning. INF1000 Forelesning 7. Oppførselen til inword()/inint()/etc. Operator-presedens i Java

Løse reelle problemer

Oblig 4 (av 4) INF1000, høsten 2012 Værdata, leveres innen 9. nov. kl

ALGORITMER OG DATASTRUKTURER

BOKMÅL Side 1 av 5. KONTERINGSEKSAMEN I FAG TDT4102 Prosedyre og objektorientert programmering. Onsdag 6. august 2008 Kl

Obligatorisk oppgave 1 INF1020 h2005

[Kurssidene] [ ABI - fagsider bibin ] Michael Preminger (michaelp@hio.no) 07/ Vi holder orden på verdier med hjelp av variabler

Leksjon 3. Kontrollstrukturer

Programmeringsspråket C Del 3

MAT1030 Diskret matematikk

Abaris-notat Teknisk beskrivelse av kodeverkskomponent for ICPC-2

Obligatorisk Innlevering 2

Generiske mekanismer i statisk typede programmeringsspråk

Transkript:

INF-5110 Oppgaver kodegenerering, 7/5-09 Oppgave 1: Løs oppgavene 8.1 og 8.2 i Louden Oppgave 2: Løs oppgave 8.14.a i Louden. I stedet for oppgave 8.14.b, finn en tredje møte å implemetere switch/case på (ikke en serie tester og ikke en ren hopp-tabell) som kan være et godt kompromiss i mange tilfeller. Oppgave 3: Vi skal se på koden generert av TA-instruksjonene til høyre i figur 9.10 i detutdeltenotatet, side 539 (men finnesogsåpåsisteside i lysarkenefra5/5-09, dog med en trykkfeil: "SUB a, R1" skal rettes til "SUB c, R1"). a) Påvis at det finnes en bedre kodesekvens for de samme TA-setningene enn den angitte, som er generert av notatets algoritme. b) Diskuter hvordan vi kunne forandre denne kodegenererings-algoritmen, slik at den gir bedre kode i dette tilfellet. Oppgave 4: Løs Oppgave 4 fra eksamen 2007. Denne ligger på: http://www.uio.no/studier/emner/matnat/ifi/inf5110/v08/undervisningsmateriale/inf5110-eksamen2007.pdf Oppgave 5: a) Oversett (pr hånd) følgende setning til TA-kode: if a<b (c>d && e>=f) then x=8 else y=5 endif Oversett den til kode der alle hopp blir så direkte som over hodet mulig (uten å tenke på algoritmen for å gjøre det). b) Forsøk å tenke ut kodegenererings-algoritmer som kunne generere slik kode, f.eks. for setningen over.

Oppgave 1: Løs oppgavene 8.1 i Louden 2 + 3 + 4 + 5 : ------------------ t1 = 2 + 3 t2 = t1 + 4 t3 = t2 + 5 2 + (3 + (4 + 5)) : ------------------------ t1 = 4 + 5 t2 = 3 + t1 t3 = 2 + t2 a * b + a * b * c : ----------------------- t1 = a * b t2 = t1 * c t3 = t1 + t2 Her er altså den siste hårfint optimalisert (har oppdaget felles sub-uttrykk). En liten optimalisering av de to første (gjøre konstantbergeninger i kompiloatoren) ville lett optimalisert de to første til t1 = 14

Oppgave 1: Løs oppgavene 8.2 i Louden 2 + 3 + 4 + 5 : ------------------ ldc 2 idc 3 adi ldc 4 adi ldc 5 adi 2 + (3 + (4 + 5)) : ------------------------ ldc 2 idc 3 ldc 4 ldc 5 adi adi adi a * b + a * b * c : ----------------------- ld a ld b mpi dup //dupliserer toppen ld c mpi adi Her er igjen den siste hårfint optimalisert, ved at vi antar at det er en dup-instruksjon (duplisering) i P-kode. De to første kan selvfølgelig også optimaliseres som før til ldc 14

Oppgave 2 Løs oppgave 8.14.a i Louden. I stedet for oppgave 8.14.b, finn en tredje møte å implemetere switch/case på (ikke en serie tester og ikke en ren hopp-tabell) som kan være et godt kompromiss i mange tilfeller. a) Vitsen med en hopptabell er at man skal kunne gå rett inn i tabellen med caseindeksen, og at hopp-adressen står der. Det blir altså meget raskt, men tabellen må da spenne fra laveste til høyeste brukte indeks. Om det ikke er så mange brukte indekser, og avstanden mellom største og minste brukte indeks er stor kan tabellen bruke masse plass, men det meste av den vil være tom. Da kan en if-then-else-implementasjon med test på hvert tilfelle være like grei. Ny b) En tredje implementasjon kan være å sortere de brukte indeksverdiene, og så legge disse i en tabell med hopp-adressen ved siden av. Da kan man ved runtime bruke binærsøking til å finne om indeksen er der, og hvor det eventuelt skal hoppes.

Oppgave 3 Vi skal se på koden generert av TA-instruksjonene til høyre i figur 9.10 i det utdelte notatet, side 539 (men finnes også på siste side i lysarkene fra 5/5-09, dog med en trykkfeil: "SUB a, R1" skal rettes til "SUB c, R1"). a) Påvis at det finnes en bedre kodesekvens for de samme TA-setningene enn den angitte, som er generert av notatets algoritme. SVAR: Det dumme er at vi henter opp a to ganger fra lageret. Om vi allerede første gang hadde sett at vi trengte den en gang til så kunne vi med en gang kopiert den over i et annet register (for eksempel R1) før vi ødela verdien av a i R0 med instruksjonen SUB b, R0. Da ville de første instruksjonene bli: MOV a, R0 MOV R0, R1 // er altså billigere enn en MOV fra lager til register SUB b, R0 SUB c, R0 b) Diskuter hvordan vi kunne forandre denne kodegenererings-algoritmen, slik at den gir bedre kode i dette tilfellet. SVAR: Vi har jo allerede informasjon nok til å kunne gjøre denne optimaliseringen, i og med next use. Vi kan se at den første a -en har en next-use (og til og med at den har det allerede i neste injstruksjon), og da kan vi redde verdien unna i et ledig register om et slik finnes (med en MOV mellom registere)

Til oppgave 3: Eksempel på kode-generering Setninger Generert kode Reg. deskriptorer Adr. deskriptorer Alle Reg er ubrukte t = a - b MOV a, R0 R0 inneholder t t i R0 SUB b, R0 u = a c MOV a, R1 SUB c, R1 R0 inneholder t R1 inneholder u t i R0 u i R1 v = t + u ADD R1, R0 R0 inneholder v v i R0 R1 inneholder u u i R1 d = v + u ADD R1, R0 R0 inneholder d d i R0 og ikke i hukommelsen Avslutning av basal blokk MOV R0, d Alle Reg er ubrukte (Alle prog.variable i hukommelsen) 6

Oppgave 4a, eksamen 2007 Gitt følgende program, der alle setningene er tre-addresseinstruksjoner, bortsett fra at vi også tillater if- og while-setninger på vanlig måte. Instruksjonene x = input og output x regnes som vanlige tre-addresse-instruksjoner, med den opplagte betydning. Vi antar at ingen variable er i live ved slutten av programmet. 1: a = input 2: b = input 3: d = a + b 4: c = a * d 5: if ( b < 5 ) { 6: while ( b < 0 ) { 7: a = b + 2 8: b = b + 1 9: } 10: d = 2 * b 11: } else { 12: d = b * 3 13: a = d - b 14: } 15: output a 16: output d 4a Angi for hver av variablene a, b, c og d om de er i live eller ikke umiddelbart etter linje 4. Gi en kort forklaring for hver av variablene. Svar: a. Det kunne se ut som om denne var død, siden den settes ( defineres ) både i den ene og den andre grenen av if-setningen, uten å bli brukt først (linje 7 og linje 13). Men, dersom while-løkke går null ganger vil den verdien som a hadde etter linje 4 være den som brukes i linje 15. Altså er den i live. b. Denne er i høyeste grad live, siden den brukes allerede i linje 5 c. Dennebrukesi detheletattikkeetterlinje4, oger derfor ikke i live (altså død). d. Denne er ikke i live, siden den helt sikkert settes i begge if-grener, uten å bli brukt først (linje 10 og 12).

Oppgave 4b, eksamen 2007 4b Forklar hva man i kodegenererings-algoritmen i kap 9.6 (i den utdelte kopien fra ASU-boka) mener med at en variabel har en neste bruk ( next use ) og hvordan dette skiller seg fra å være i live. Forklar hvorfor denne algoritmen skiller mellom disse to begrepene. Svar: Begrepet neste bruk er, i motsetning til begrepet i live knyttet til basale blokker. En variabel har på et gitt sted i programmet en neste bruk dersom den verdien den der har kan bli brukt senere i den basale blokka vi nå er i. (da kan man også si at verdien til variabelen vil bli brukt senere i blokka, siden alt i en basal blokk utføres pent etter hverandre). Grunnen til at algoritmen i notatet er interessert i neste bruk (i den basale blokka) er at den har som grunnfilosofi at ingen variable som er i live skal ligge i et register (men i hjemmeposisjonen sin) mellom basale blokker. Det gjøres altså ikke noe forsøk på å optimalisere over flere basale blokker. Dermed, om en ikke har noen neste bruk i blokka, så er det ingen fordeler med å la den ligge i et register (men om den er i live må man sørge for at verdien ligger i hjemmeposisjonen). (NB: Ordet hjemmeposisjon er ikke brukt i boka. Der snakker man heller om å ha variabel-verdier i et register, og to store them, når de må kopieres til sin variabel-posisjon.)

Oppgave 5 a) a) Oversett (pr hånd) følgende setning til TA-kode: if a<b (c>d && e>=f) then x=8 else y=5 endif Oversett den til kode der alle hopp blir så direkte som over hodet mulig (uten å tenke på algoritmen for å gjøre det). SVAR: t1 = a < b if_true t1 goto 1 // Vi vet at uttrykket er sant t2 = c > d if_false t2 goto 2 // Vi vet at uttrykket er galt t3 = e >= f if_false t3 goto 2 // Vi vet at uttrykket er galt, ellers er det sant og vi fortsetter label 1 x = 8 goto 3 label 2 y = 5 label 3

Oppgave 5 b) b) Forsøk å tenke ut kodegenererings-algoritmer som kunne generere slik kode, f.eks. for setningen over. SVAR: Hovedsaken med den koden som er angitt i 5 a) er altså at man aldri beregner den logiske verdien på hele det boolske uttrykket, og at så fort man har nok informasjon til å vite om uttrykket blir true eller false, så hopper man direkte til den grenen der dette tilfellet skal behandles. Hvordan slik kode kan genereres vil avhenge veldig om vi bare skal ha symbolske labeler som vi kan velge fritt, eller om hoppene skal gå til faktiske fysiske adresser, f.eks. til der else-grenen starter (som ikke er kjent når det boolske uttrykket behandles). Det siste tilfellet er verst. Da kan man generere hopp med tomme adresser der man vet det skal inn hopp til f.eks. en else-gren, og det kan for samme else-gren bli mange slike hopp etter hvert. Man må da holde lister med adressene til alle de hopp som skal gå for eksempel til then-grenen og til else-grenen, og når vi en gang kommer til disse grenene (og vet deres start-adresse) må man gå tilbake i listen og sette inn adressen i alloe de rette hopp-instruksjonene. Merk at man da også må være nøye med om det er på true eller false man skal hoppe

Litt om Javas class-filer og byte-kode Ikke pensum, men anbefales lest som bakgrunnsmateriale Disse formatene ble planlagt fra start som en del av hele Javaideen Byte-koden gir portabilitet ved at den utføres av en interpretator (som må skrives for hver enkelt maskin, gjerne i C eller C++) Gir, sammen med et standard bibliotek, et enhetlig grensesnitt til operativsystemet, grafikk, osv. fra Java Samme Java-kompilator kan dermed brukes på alle maskiner For effektivitet: Byte-koden blir nå ofte oversatt til maskinkode før utførelse, enten i en egen kompilerings-operasjon, eller som JITkompilering som en del av loadinga. Likner mye på den lavnivå-koden dere oversetter til i Oblig 2 Men hos dere blir også Loading gjort samtiding som koden blir laget. I Javas byte-kode blir alle navn beholdt på tekstlig form i den bytekoden som legges på fil (som klasse-filer) Først når denne taes inn av loaderen blir den laget om til binær kode. 11

Litt om Javas class-filer og byte-kode Formatet av class-filene inneholder både Den utførbare koden (som byte-kode = sekvenser av byteinstruksjoner), Og hele strukturen av klassen, med info om navn, variable, metoder, parametere, typer, etc. Disse to informasjonstypene ligger tradisjonelt på to forskjellige filer: For C og C++, på.c-filer (som oversettes til maskinkode) og på.h-filer En class-fil leses derved i to sammenhenger i forbindelse med kompilering/kjøring: Når en annen klasse som referer til denne (f.eks. en subklasse) kompileres: Da ser man mest på struktur-delen av klasse-filen Når klassen skal loades: Da ser man mest på byte-koden for hver av metodene i klassen 12

Formatet av Javas class-filer På hver class-fil er det bare beskrivelse av én klasse eller ett grensesnitt class-filene har all informasjon om: Navn på klassen, og på superklassen og implementerte grensesnitt Hvilke variable klassen har, ved navn, type og synlighet Hvilke metoder den har, ved navn, type, synlighet, parametere (med typer), og byte-kode-sekvens class-filene har også et navne-område eller et konstant-område Her ligger alle tekster, navn, og tall-verdier (på tekstlig form) som brukes i programmet, pent etter hverandre. Når disse skal brukes ellers i klassefila (f.eks. i selve byte-koden) så angir man bare indeksen til dette navnet i navne-området. 13

Formatet av byte-koden Byte-koden har samme idé som P-koden, ved at arbeids-dataene skal ligge på en stakk under utførelsen Funksjons-delen av instruksjonen er på én byte, altså plass til 256 instruksjoner (som faktisk er litt lite) Byte-instruksjonenes adressefelt (der dette trengs) angis ved fullt navn (tekstlig), type og klasse-tilhørighet Det eneste unntaket fra dette er lokale variable i metoder. Disse angis som relativ-adresse (i byte) i aktiverings-blokken. Som antydet på forrige foil: Det blir mange navn det stadig skal refereres til. Derfor ligger navnene bare én gang hver i et eget navne-område, og de angis andre steder bare ved en indeks inn i dette området 14

Hva foregår i en Java Virtual Machine (JVM) En JVM kan enten interpretere eller oversette til maskinkode (JIT, eller vanlig) Den består av en loader, en verifikator, samt av en interpretator eller en oversetter Loaderen starter med å lese inn og behandle den angitte class-fila Leser så etter hvert inn alle class-filer som det referers til fra denne, osv. Lager en descriptor for hver klasse. Denne vil ligge fast under den kommende utførelse av programmet Alle objekter har en peker til descriptoren for sin klasse Descriptoren inneholder virtuell-tabellen for klassen, en peker til descriptoren for superklassen, etc. Dersom debugging eller refleksivitet: Descriptoren inneholder også info om alle variable/metoder Descriptoren kan også ha en peker til et sted der selve Java-koden ligger 15

Mer om: Hva foregår i en JVM Loaderen gjør allokering av variable i klassene, dvs.: Går gjennom byte-kode-sekvensen og gjør hver av de tekstlige operandene om til relativadresser, og alle klasse-angivelser (f.eks. i casting og ved new C ) om til pekere til klassens descriptor Merk at allokering av én klasse må gjøres før allokering for dens subklasser Dersom interpretering: Legger sekvensen av byte-instruksjoner (nå med tall både for funksjonsangivelse og adresser) ut i et passelig format Starter å interpretere dette Dersom oversetting: Oversetter sekvensen byte-instruksjoner til maskinkode for gitt maskin Kan også gjøres som en vanlig forhåndskompilering, eller en JIT-kompilering (Just-In-Time) i forbindelse med at programmet skal startes opp. Kan også gjøre noe midt i mellom: Interpretere først, men etter hvert oversette de metoder som brukes mest. Finnes også Java-kompilatorer som hopper over hele byte-kode-steget Får da en tradisjonell kompilator, som kan lage effektiv kode Men det er mer problematisk å koble seg til Javas standard-bibliotek etc. 16

Verifikatoren Denne kan gå gjennom klassefiler og sjekke at de er konsistente Spesielt sjekke at bytekoden er konsistent (se under) Og at den ikke gjør noe den ikke har autorisasjon til Dette er spesielt aktuelt for class-filer som hentes inn over nettet Hva gjør verifikatoren med byte-koden: Simulerer hele tiden hva som vil ligge på stakken under utførelsen Sjekker at det som ligger på toppen av stakken hele tiden stemmer typemessig etc. med den instruksjonen som skal utføres Sjekker at når det gjøres hopp så er stakken helt lik der det hoppes fra og der det hoppes til. Sjekker at de operasjonene som gjøres er lovlige (i henhold til autorisasjon) 17

Java-program: Typisk Byte-kode, ferdig til interpretering: Merk: Også funsjonskodene (f.eks. sipush, iconst_2 og goto) er nå gjort om til tallkoder (mellom 0 og 255) outer: for (int i = 2; i < 1000; i++) { for (int j = 2; j < i; j++) { if (i % j == 0) continue outer; } System.out.println (i); } 0: iconst_2 1: istore_1 // i har reladr 1 2: iload_1 3: sipush 1000 6: if_icmpge 44 9: iconst_2 10: istore_2 // j har reladr 2 11: iload_2 12: iload_1 13: if_icmpge 31 16: iload_1 17: iload_2 18: irem # remainder 19: ifne 25 22: goto 38 25: iinc_2, 1 28: goto 11 31: getstatic #84; // Området for println()? 34: iload_1 35: invokevirtual #85; // println() 38: iinc 1, 1 41: goto 2 44: return 18