En compiler er et program, der oversætter tekst skrevet på et programmeringssprog til et sæt maskinkoder [1] [2] [3] .
Kompilering - samling af programmet, herunder:
Hvis compileren genererer et eksekverbart maskinsprogsprogram, så udføres et sådant program direkte af en fysisk programmerbar maskine (f.eks. en computer). I andre tilfælde udføres det eksekverbare maskinprogram af den tilsvarende virtuelle maskine .
Kompilerens input er:
Outputtet fra compileren er en tilsvarende beskrivelse af algoritmen i et maskinorienteret sprog (objektkode [5] , bytecode ).
Kompilere - for at samle et maskinprogram, herunder:
Ganske ofte udfører compilere fra sprog på højt niveau kun oversættelse af kildekoden, mens de overlader linkningen til en ekstern linker, en linker, der repræsenterer et uafhængigt program kaldet af compileren som en ekstern subrutine. Som følge heraf anses kompilatoren af mange for at være en slags oversætter, hvilket er forkert ...
Alle compilere kan også betinget opdeles i to grupper:
Kompileringstyper [2] :
Kompileringsprocessen består af følgende trin:
Strukturelle compilerimplementeringer kan være som følger:
Ifølge den første ordning blev de allerførste kompilatorer bygget - for moderne compilere er en sådan konstruktionsordning ukarakteristisk.
Ifølge den anden ordning er alle compilere fra højniveausprog uden undtagelse bygget. Enhver sådan compiler udfører kun oversættelse og kalder derefter linkeren som en ekstern subrutine, som forbinder det maskinorienterede program. En sådan konstruktionsordning gør det nemt for compileren at arbejde i oversættertilstand fra det tilsvarende programmeringssprog. Denne omstændighed tjener ofte som en grund til at betragte compileren som en slags oversætter, hvilket naturligvis er forkert - alle moderne compilere af denne type udfører stadig links, dog ved hjælp af den eksterne linker, der kaldes af compileren, mens compileren selv aldrig kalder den eksterne linker. Men den samme omstændighed gør det muligt for compileren fra et programmeringssprog i forbindelsesfasen at inkludere i programmet skrevet i et programmeringssprog funktioner-underrutiner fra dem, der allerede er oversat af den tilsvarende compiler/compiler, skrevet i et andet programmeringssprog. Så du kan indsætte funktioner skrevet i Pascal eller Fortran i et C/C++ program . På samme måde, og omvendt, kan funktioner skrevet i C/C++ indsættes i henholdsvis et Pascal- eller Fortran-program. Dette ville være umuligt uden støtte fra mange moderne compilere til at generere kode til opkaldsprocedurer (funktioner) i overensstemmelse med konventionerne for andre programmeringssprog. For eksempel understøtter moderne compilere fra Pascal-sproget, udover at organisere procedure-/funktionskald i selve Pascal-standarden, organiseringen af et procedure-/funktionskald i overensstemmelse med C/C++ sprogkonventioner. (For at en procedure/funktion skrevet i Pascal f.eks. kan arbejde med inputparametre på maskinkodeniveau i overensstemmelse med konventionerne for C/C++ sproget, skal erklæringen for en sådan Pascal-procedure/Pascal-funktion indeholde cdecl nøgleordet .)
Endelig, ifølge den tredje ordning, bygges compilere, som er hele systemer, der inkluderer oversættere fra forskellige programmeringssprog og linkere. Enhver sådan compiler kan også bruge enhver oversætter-kompiler fra et bestemt højt niveau sprog som oversætter. Naturligvis kan en sådan compiler kompilere et program, hvis forskellige dele af kildeteksten er skrevet på forskellige programmeringssprog. Ofte styres sådanne kompilatorer af en indbygget fortolker af et eller andet kommandosprog. Et slående eksempel på sådanne compilere er make compileren tilgængelig på alle UNIX-systemer (især på Linux) .
Oversættelse af programmet som en integreret del af kompilationen inkluderer:
De fleste compilere oversætter et program fra et eller andet højt niveau programmeringssprog til maskinkode, der kan udføres direkte af en fysisk processor . Som regel er denne kode også fokuseret på eksekvering i et specifikt operativsystems miljø , da den bruger de muligheder, den giver ( systemkald , funktionsbiblioteker). Arkitekturen (sæt af software og hardware), som et maskinorienteret program er kompileret (samlet) til, kaldes målmaskinen .
Resultatet af kompilering - et eksekverbart programmodul - har den højest mulige ydeevne, men er bundet til et specifikt operativsystem (OS-familie eller underfamilie) og processor (processorfamilie) og vil ikke fungere på andre.
Hver målmaskine ( IBM , Apple , Sun , Elbrus , osv.) og hvert operativsystem eller familie af operativsystemer, der kører på målmaskinen, kræver at skrive sin egen compiler. Der er også såkaldte cross-compilere , der tillader, på én maskine og i miljøet af et OS, at generere kode beregnet til udførelse på en anden målmaskine og/eller i miljøet af et andet OS. Derudover kan compilere optimere kode til forskellige modeller fra den samme processorfamilie (ved at understøtte modelspecifikke funktioner eller instruktionssætudvidelser). For eksempel kan kode kompileret til processorer i Pentium -familien tage højde for funktionerne i parallelisering af instruktioner og bruge deres specifikke udvidelser - MMX , SSE , osv.
Nogle compilere oversætter et program fra et sprog på højt niveau, ikke direkte til maskinkode, men til assemblersprog . (Eksempel: PureBasic , oversættelse af BASIC-kode til FASM assembler .) Dette gøres for at forenkle kodegenereringsdelen af compileren og øge dens portabilitet (opgaven med den endelige kodegenerering og at linke den til den påkrævede målplatform flyttes til assembler ), eller for at kunne styre og korrigere kompileringsresultatet (inklusive manuel optimering) af programmøren.
Resultatet af compilerens arbejde kan være et program i et specielt oprettet lavniveausprog med binære kodekommandoer udført af en virtuel maskine . Et sådant sprog kaldes pseudokode eller bytekode . Som regel er det ikke maskinkoden på nogen computer, og programmer på den kan udføres på forskellige arkitekturer, hvor der er en tilsvarende virtuel maskine, men i nogle tilfælde oprettes hardwareplatforme, der direkte udfører pseudokoden for ethvert sprog . For eksempel kaldes Java -sprogpseudokode Java- bytecode og kører i Java Virtual Machine , og picoJava- processorspecifikationen blev oprettet til dens direkte udførelse . For .NET Framework kaldes pseudokoden Common Intermediate Language (CIL), og kørselstiden kaldes Common Language Runtime (CLR).
Nogle implementeringer af fortolkede sprog på højt niveau (såsom Perl) bruger bytekode til at optimere eksekveringen: de dyre trin med at parse og konvertere programtekst til bytekode udføres én gang ved indlæsning, hvorefter den tilsvarende kode kan genbruges uden genkompilering.
På grund af behovet for fortolkning kører bytekode meget langsommere end maskinkode med sammenlignelig funktionalitet, men den er mere bærbar (afhænger ikke af operativsystemet og processormodellen). For at fremskynde eksekveringen af bytekoden bruges dynamisk kompilering , når den virtuelle maskine oversætter pseudokoden til maskinkode umiddelbart før dens første eksekvering (og når koden tilgås gentagne gange, udføres den allerede kompilerede version).
Den mest populære type dynamisk kompilering er JIT . En anden variation er inkrementel kompilering .
CIL-kode kompileres også til målmaskinekode af JIT-kompileren, mens .NET Framework -biblioteker er prækompileret.
Oversættelsen af bytekode til maskinkode med en speciel bytekodeoversætter som nævnt ovenfor er en integreret fase af dynamisk kompilering. Men bytekodeoversættelse er også nyttig til blot at konvertere et bytekodeprogram til et tilsvarende maskinsprogsprogram. Det kan oversættes til maskinkode som prækompileret bytekode. Men også oversættelsen af bytekode til maskinkode kan udføres af bytekodekompileren umiddelbart efter kompileringen af bytekoden. Næsten altid i sidstnævnte tilfælde udføres bytekode-oversættelse af en ekstern oversætter kaldet af bytekode-kompileren.
Der er programmer, der løser det omvendte problem - at oversætte et program fra et lavniveausprog til et højtniveau. Denne proces kaldes dekompilering, og sådanne programmer kaldes decompilere . Men da kompilering er en tabsgivende proces, er det generelt ikke muligt nøjagtigt at gendanne kildekoden i f.eks. C++. Programmer i bytekoder dekompileres mere effektivt - for eksempel er der en ret pålidelig decompiler til Flash . En variation af dekompilering er adskillelsen af maskinkode til assemblersprogkode, som næsten altid udføres sikkert (i dette tilfælde kan kompleksiteten være selvmodificerende kode eller kode, hvor den faktiske kode og data ikke er adskilt). Det skyldes, at der næsten er en-til-en overensstemmelse mellem maskininstruktionskoder og montageanvisninger.
Separat kompilering ( eng. separate compilation ) - oversættelse af dele af programmet separat med deres efterfølgende kombination af linkeren til et enkelt load-modul [2] .
Historisk set var et træk ved compileren, afspejlet i dens navn ( eng. compile - put together, compose), at den producerede både oversættelse og linkning, mens compileren umiddelbart kunne generere maskinkode . Men senere, med den stigende kompleksitet og størrelse af programmer (og stigende tid brugt på rekompilering), blev det nødvendigt at adskille programmer i dele og isolere biblioteker , der kan kompileres uafhængigt af hinanden. I processen med at oversætte et program, genererer compileren selv, eller en compiler kaldet af compileren, et objektmodul indeholdende yderligere information, som så - i færd med at linke dele til et eksekverbart modul - bruges til at linke og løse referencer mellem dele af programmet. Separat kompilering giver dig også mulighed for at skrive forskellige dele af et programs kildekode på forskellige programmeringssprog.
Fremkomsten af separat kompilering og tildelingen af linkning som et separat trin opstod meget senere end oprettelsen af compilere. I denne henseende, i stedet for udtrykket "kompilator", bruges udtrykket "oversætter" nogle gange som dets synonym: enten i den gamle litteratur, eller når de ønsker at understrege dets evne til at oversætte et program til maskinkode (og vice versa, de bruger udtrykket "compiler" for at understrege evnen til at samle fra mange filer en). Det er bare brugen af udtrykkene "kompilator" og "oversætter" i denne sammenhæng er forkert. Selvom compileren udfører oversættelsen af selve programmet, uddelegerer linkningen til det påkaldte eksterne linkerprogram, kan en sådan compiler ikke betragtes som en slags oversætter - oversætteren udfører oversættelsen af kildeprogrammet og intet mere. Og bestemt ikke oversættere er kompilatorer som make -systemkompilerværktøjet, der findes på alle UNIX-systemer.
Selve make -værktøjet er et glimrende eksempel på en ret vellykket implementering af separat kompilering. Funktionen af make -hjælpeprogrammet styres af et script på inputsproget, der fortolkes af hjælpeprogrammet, kendt som makefile , indeholdt i inputtekstfilen, der er angivet, når hjælpeprogrammet køres. Værktøjet udfører ikke selv nogen oversættelse eller linkning - de facto fungerer make -værktøjet som en kompileringsprocesstyring, der organiserer kompileringen af programmet i overensstemmelse med det specificerede script. Især under kompileringen af målprogrammet kalder hjælpeprogrammet kompilatorer fra programmeringssprog, der oversætter forskellige dele af kildeprogrammet til objektkode, og derefter kaldes en eller anden linker, der forbinder det endelige eksekverbare program eller bibliotek programmodul. Samtidig kan forskellige dele af programmet, arrangeret som separate kildetekstfiler, skrives både på samme programmeringssprog og på forskellige programmeringssprog. Under genkompileringen af programmet oversættes kun de ændrede dele-filer af programmets kildekode, hvilket resulterer i, at varigheden af genkompileringen af programmet reduceres betydeligt (nogle gange i en størrelsesorden).
I begyndelsen af udviklingen af computere blev de første oversættere (oversættere) kaldt "programmeringsprogrammer" [6] (da det på det tidspunkt kun var maskinkode, der blev betragtet som et program, og et "programmeringsprogram" var i stand til at lave maskinkode fra menneskelig tekst, det vil sige programmering af en computer ).
Ordbøger og encyklopædier | ||||
---|---|---|---|---|
|