Articles

Subrutine

ideen om en subrutine ble utarbeidet etter at databehandlingsmaskiner allerede hadde eksistert i noen tid.De aritmetiske og betingede hoppinstruksjonene ble planlagt på forhånd og har endret seg relativt lite, men de spesielle instruksjonene som brukes til prosedyreanrop har endret seg sterkt gjennom årene.De tidligste datamaskiner og mikroprosessorer, Som Manchester Baby og RCA 1802, hadde ikke en eneste subrutine samtale instruksjon.Subrutiner kunne implementeres, men de krevde programmerere å bruke anropssekvensen – en rekke instruksjoner-på hvert anropssted.

Subrutiner ble implementert I Konrad Zuses Z4 i 1945.I 1945 brukte Alan M. Turing begrepene «bury» og «unbury» som et middel til å ringe og returnere fra subrutiner.I januar 1947 presenterte John Mauchly generelle notater på ‘Et Symposium Av Storskala Digital Beregning Maskiner’ under felles sponsing Av Harvard University og Bureau Of Ordnance, United States Navy. Her diskuterer han seriell og parallell operasjon som tyder på

…strukturen på maskinen trenger ikke være komplisert en bit. Det er mulig, siden alle de logiske egenskapene som er avgjørende for denne prosedyren er tilgjengelige, å utvikle en kodingsinstruksjon for å plassere subrutinene i minnet på steder som er kjent for maskinen, og på en slik måte at de lett kan tas i bruk.

med Andre ord kan man betegne subrutine A som divisjon og subrutine B som kompleks multiplikasjon Og subrutine C som evaluering av en standardfeil i en sekvens av tall, og så videre gjennom listen over subrutiner som trengs for et bestemt problem. … Alle disse subrutinene vil da bli lagret i maskinen, og alt man trenger å gjøre er å lage en kort referanse til dem etter nummer, som de er angitt i kodingen.

Kay McNulty hadde jobbet tett med John Mauchly på eniac-teamet og utviklet en ide for subrutiner for eniac-datamaskinen hun programmerte under Andre Verdenskrig. Hun og de ANDRE eniac-programmererne brukte subrutinene til å beregne missilbaner.Goldstine og von Neumann skrev en artikkel datert 16. August 1948 om bruken av subrutiner.NOEN svært tidlige datamaskiner og mikroprosessorer, SLIK SOM IBM 1620, Intel 4004 og Intel 8008, og pic mikrokontrollere, har en enkelt instruksjon subrutine samtale som bruker en dedikert maskinvarestabel til å lagre returadresser—slik maskinvare støtter bare noen få nivåer av subrutine nesting, men kan støtte rekursive subrutiner. Maskiner før midten av 1960—tallet-SOM UNIVAC I, PDP—1 og IBM 1130-bruker vanligvis en kallekonvensjon som lagret instruksjonstelleren i den første minneplasseringen til den kalt subrutinen. Dette tillater vilkårlig dype nivåer av subrutin nesting, men støtter ikke rekursive subrutiner. PDP-11 (1970) er en av de første datamaskinene med en stack-pushing subrutine call instruksjon; denne funksjonen støtter både vilkårlig dyp subrutine nesting og støtter også rekursive subrutiner.

Språk supportEdit

i de aller tidlige montører, subrutine støtte var begrenset. Subrutiner ble ikke eksplisitt skilt fra hverandre eller fra hovedprogrammet, og faktisk kunne kildekoden til en subrutine blandes med den for andre underprogrammer. Noen montører vil tilby forhåndsdefinerte makroer for å generere anrops-og retursekvenser. Ved 1960-tallet hadde montører vanligvis mye mer sofistikert støtte for både inline og separat monterte subrutiner som kunne kobles sammen.

Subrutine librariesEdit

selv med denne besværlige tilnærmingen viste subrutiner seg å være svært nyttige. For det første tillot de bruk av samme kode i mange forskjellige programmer. Videre var minnet en svært knapp ressurs på tidlige datamaskiner, og subrutiner tillot betydelige besparelser i størrelsen på programmer.

Mange tidlige datamaskiner lastet programinstruksjonene inn i minnet fra en stanset papirtape. Hver subrutine kan deretter leveres av et eget stykke tape, lastet eller spleiset før eller etter hovedprogrammet (eller» mainline»); og det samme subrutine-båndet kan da brukes av mange forskjellige programmer. En lignende tilnærming brukt i datamaskiner som brukte stansede kort for deres hovedinngang. Navnet subrutine library betydde opprinnelig et bibliotek, i bokstavelig forstand, som holdt indekserte samlinger av bånd eller kortdekk for kollektiv bruk.

Return by indirect jumpEdit

for å fjerne behovet for selvmodifiserende kode, ga datamaskindesignere til slutt en indirekte hoppeinstruksjon, hvis operand, i stedet for å være returadressen selv, var plasseringen av en variabel eller prosessorregister som inneholdt returadressen.

på disse datamaskinene, i stedet for å endre subrutinens returhopp, ville kalleprogrammet lagre returadressen i en variabel slik at når subrutinen ble fullført, ville den utføre et indirekte hopp som ville lede utførelsen til stedet gitt av den forhåndsdefinerte variabelen.

Hopp til subrutineedit

Et annet fremskritt var hopp til subrutine-instruksjonen, som kombinerte lagring av returadressen med kallehoppet, og minimerte dermed overhead betydelig.

I IBM System / 360 vil for EKSEMPEL filialinstruksjonene BAL eller BALR, designet FOR prosedyrekall, lagre returadressen i et prosessorregister spesifisert i instruksjonen, ved konvensjonsregister 14. For å returnere, hadde subrutinen bare å utføre en indirekte filialinstruksjon (BR) gjennom det registeret. Hvis subrutinen trengte det registeret for et annet formål( for eksempel å ringe en annen subrutine), ville det lagre registerets innhold til et privat minnested eller en registerstabel.

i systemer SOM HP 2100 ville jsb-instruksjonen utføre en lignende oppgave, bortsett fra at returadressen ble lagret i minnestedet som var målet for grenen. Utførelse av prosedyren vil faktisk begynne på neste minnested. I HP 2100 assembly language, ville man skrive, for eksempel

 ... JSB MYSUB (Calls subroutine MYSUB.) BB ... (Will return here after MYSUB is done.)

for å ringe EN subrutine kalt MYSUB fra hovedprogrammet. Subrutinen ville bli kodet som

 MYSUB NOP (Storage for MYSUB's return address.) AA ... (Start of MYSUB's body.) ... JMP MYSUB,I (Returns to the calling program.)

jsb-instruksjonen plasserte adressen TIL NESTE instruksjon (NEMLIG BB) i stedet angitt som operand (NEMLIG MYSUB), og deretter forgrenet til NESTE sted etter det (NEMLIG AA = MYSUB + 1). Subrutinen kan da gå tilbake til hovedprogrammet ved å utføre det indirekte hoppet JMP MYSUB, jeg som forgrenet til stedet lagret PÅ location MYSUB.

Kompilatorer For Fortran og andre språk kan enkelt gjøre bruk av disse instruksjonene når de er tilgjengelige. Denne tilnærmingen støttet flere nivåer av samtaler; men siden returadresse, parametere og returverdier for en subrutine ble tildelt faste minnesteder, tillot det ikke rekursive anrop.For Øvrig ble En lignende metode brukt Av Lotus 1-2-3, tidlig på 1980-tallet, for å oppdage omberegningsavhengighetene i et regneark. Nemlig ble et sted reservert i hver celle for å lagre returadressen. Siden sirkelreferanser ikke er tillatt for naturlig omberegning, tillater dette at et tre går uten å reservere plass til en stabel i minnet, noe som var svært begrenset på små datamaskiner som IBM PC.

Call stackEdit

De fleste moderne implementeringer av et subrutineanrop bruker en anropsstabel, et spesielt tilfelle av stackdatastrukturen, for å implementere subrutineanrop og retur. Hvert prosedyrekall oppretter en ny oppføring, kalt en stakkramme, øverst i stabelen; når prosedyren returnerer, slettes stakkrammen fra stakken, og plassen kan brukes til andre prosedyrekall. Hver stakkramme inneholder de private dataene for det tilsvarende anropet, som vanligvis inkluderer prosedyrens parametere og interne variabler og returadressen.anropssekvensen kan implementeres av en sekvens av ordinære instruksjoner (en tilnærming som fortsatt brukes i risc (reduced instruction set computing) og very long instruction word (VLIW) arkitekturer), men mange tradisjonelle maskiner designet siden slutten av 1960-tallet har inkludert spesielle instruksjoner for dette formålet.

anropsstakken implementeres vanligvis som et sammenhengende område med minne. Det er et vilkårlig designvalg om bunnen av stabelen er den laveste eller høyeste adressen innenfor dette området, slik at stabelen kan vokse fremover eller bakover i minnet; imidlertid valgte mange arkitekturer sistnevnte.Noen design, spesielt Noen Forth implementeringer, brukte to separate stabler, en hovedsakelig for kontrollinformasjon (som returadresser og loop tellere) og den andre for data. Den tidligere var, eller jobbet som, en samtalestabel og var bare indirekte tilgjengelig for programmereren gjennom andre språkkonstruksjoner, mens sistnevnte var mer direkte tilgjengelig.

da stabelbaserte prosedyrekall først ble introdusert, var en viktig motivasjon å spare dyrebart minne. Med dette skjemaet trenger kompilatoren ikke å reservere separat plass i minnet for de private dataene (parametere, returadresse og lokale variabler) for hver prosedyre. Når som helst inneholder stakken bare de private dataene for samtalene som er aktive (nemlig, som har blitt kalt, men har ikke returnert ennå). På grunn av hvordan programmer vanligvis ble satt sammen fra biblioteker, var det (og er fortsatt) ikke uvanlig å finne programmer som inkluderer tusenvis av subrutiner, hvorav bare en håndfull er aktive til enhver tid. For slike programmer kan anropsstakkemekanismen spare betydelige mengder minne. Faktisk kan anropsstakkemekanismen ses som den tidligste og enkleste metoden for automatisk minnehåndtering.en annen fordel med call stack-metoden er imidlertid at den tillater rekursive subrutine-anrop, siden hvert nestede anrop til samme prosedyre får en egen forekomst av sine private data.

Forsinket stabling Rediger

en ulempe med anropsstackmekanismen er den økte kostnaden for et prosedyrekall og tilhørende retur. Ekstrakostnaden inkluderer å øke og redusere stakkpekeren (og i noen arkitekturer sjekke for stakkoverflyt), og få tilgang til de lokale variablene og parameterne etter rammerelative adresser, i stedet for absolutte adresser. Kostnaden kan realiseres i økt kjøretid, eller økt prosessorkompleksitet, eller begge deler.

denne overhead er mest åpenbar og støtende i bladprosedyrer eller bladfunksjoner, som returnerer uten å gjøre noen prosedyre kaller seg selv.For å redusere det overhead, prøver mange moderne kompilatorer å forsinke bruken av en anropsstabel til den virkelig trengs. For eksempel kan anropet Til en prosedyre p lagre returadressen og parametrene til den kalt prosedyren i visse prosessorregistre, og overføre kontrollen til prosedyrens kropp ved et enkelt hopp. Hvis prosedyren P returnerer uten å foreta et annet anrop, brukes ikke anropsstakken i det hele tatt. Hvis P må ringe en annen Prosedyre Q, vil den da bruke anropsstakken til å lagre innholdet i eventuelle registre (for eksempel returadressen) som trengs etter Q-retur.