Forsamlingssprog - Assembly language
|
| |
| Paradigme | Imperativt , ustruktureret |
|---|---|
| Første gang dukkede op | 1949 |
I programmering af computere , assembler (eller assembler sprog ), undertiden forkortet ASM , er enhver programmeringssprog lavt niveau , hvor der er en meget stærk sammenhæng mellem instruktionerne i sprog og arkitekturens maskine kode instruktioner . Fordi samlingen afhænger af maskinens kodeinstruktioner, er hvert samlingssprog designet til præcis en bestemt computerarkitektur. Monteringssprog kan også kaldes symbolsk maskinkode .
Samlingskode konverteres til eksekverbar maskinkode af et hjælpeprogram, der kaldes en assembler . Konverteringsprocessen omtales som samling , som ved samling af kildekoden . Samlingssprog har normalt en erklæring pr. Maskininstruktion (1: 1), men konstanter, kommentarer , assembler -direktiver , symbolske etiketter for program- og hukommelsesplaceringer og makroer understøttes generelt også.
Udtrykket "assembler" tilskrives generelt Wilkes , Wheeler og Gill i deres bog fra 1951 The Preparation of Programs for a Electronic Digital Computer , der dog brugte udtrykket til at betyde "et program, der samler et andet program bestående af flere sektioner i en enkelt program ".
Hvert forsamlingssprog er specifikt for en bestemt computerarkitektur og nogle gange for et operativsystem . Nogle samlingssprog giver imidlertid ikke specifik syntaks for operativsystemopkald, og de fleste samlingssprog kan bruges universelt med ethvert operativsystem, da sproget giver adgang til alle processorens reelle muligheder , som alle systemopkaldsmekanismer i sidste ende hviler på . I modsætning til samlingssprog er de fleste programmeringssprog på højt niveau generelt bærbare på tværs af flere arkitekturer, men kræver fortolkning eller kompilering , en meget mere kompliceret opgave end at samle.
Beregningstrinnet, når en assembler behandler et program, kaldes samlingstid .
Samling sprog syntaks
Forsamlingen sprog bruger en huskeregel til at repræsentere hvert lavt niveau maskine instruktion eller opcode , typisk også hver arkitektonisk register , flag osv Mange operationer kræver en eller flere operander med henblik på at danne en komplet instruktion. De fleste samlere tillader navngivne konstanter, registre og etiketter til program- og hukommelsesplaceringer og kan beregne udtryk for operander. Således er programmerere befriet for kedelige gentagne beregninger, og assembler -programmer er meget mere læsbare end maskinkode. Afhængigt af arkitekturen kan disse elementer også kombineres til specifikke instruktioner eller adressetilstande ved hjælp af forskydninger eller andre data samt faste adresser. Mange montører tilbyder yderligere mekanismer til at lette programudvikling, styre samleprocessen og hjælpe med fejlfinding .
Terminologi
- En makro assembler er en assembler, der omfatter en macroinstruction facilitet, så at (parametriseres) assembler tekst kan være repræsenteret af et navn, og dette navn kan bruges til at indsætte den udvidede tekst i anden kode.
- En krydsassembler (se også krydskompilator ) er en samler, der køres på en computer eller et operativsystem ( værtsystemet ) af en anden type end det system, hvorpå den resulterende kode skal køre ( målsystemet ). Krydsmontering letter udviklingen af programmer til systemer, der ikke har ressourcer til at understøtte softwareudvikling, f.eks. Et integreret system eller en mikrokontroller . I et sådant tilfælde skal den resulterende objektkode overføres til målsystemet via skrivebeskyttet hukommelse (ROM, EPROM osv.), En programmerer (når skrivebeskyttet hukommelse er integreret i enheden, som i mikrokontrollere) eller et datalink ved hjælp af enten en nøjagtig bit-by-bit kopi af objektkoden eller en tekstbaseret fremstilling af denne kode (f.eks. Intel hex eller Motorola S-record ).
- En assembler på højt niveau er et program, der giver sprogabstraktioner oftere associeret med sprog på højt niveau, såsom avancerede kontrolstrukturer ( HVIS/DER/ELLER , DO CASE osv.) Og abstrakte datatyper på højt niveau, herunder strukturer/ optegnelser, fagforeninger, klasser og sæt.
- En mikroassembler er et program, der hjælper med at forberede et mikroprogram , kaldet firmware , til at styre en computers drift på lavt niveau.
- En meta-assembler er "et program, der accepterer den syntaktiske og semantiske beskrivelse af et samlingssprog og genererer en assembler til det sprog". "Metasymbol" -samlere til SDS 9-serien og SDS Sigma- computere er metasamlere. Sperry Univac leverede også en Meta-Assembler til UNIVAC 1100/2200-serien .
- inline assembler (eller integreret assembler ) er assembler-kode indeholdt i et sprogprogram på højt niveau. Dette bruges oftest i systemprogrammer, der har brug for direkte adgang til hardwaren.
Nøglekoncepter
Montør
Et assembler -program skaber objektkode ved at oversætte kombinationer af mnemonik og syntaks for operationer og adresseringstilstande til deres numeriske ækvivalenter. Denne repræsentation indbefatter typisk en operationskode ( " opcode ") såvel som andre kontrol bits og data. Assembleren beregner også konstante udtryk og løser symbolske navne for hukommelsessteder og andre enheder. Brugen af symbolske referencer er et centralt træk ved montører, hvilket sparer kedelige beregninger og manuelle adresseopdateringer efter programændringer. De fleste samlere inkluderer også makrofaciliteter til at udføre tekstlig substitution - f.eks. For at generere fælles korte sekvenser af instruktioner som inline , i stedet for at kaldes underrutiner .
Nogle montører kan også være i stand til at udføre nogle enkle typer instruktionssæt -specifikke optimeringer . Et konkret eksempel på dette kan være de allestedsnærværende x86 -montører fra forskellige leverandører. De kaldes jump-sizing , de fleste af dem er i stand til at udføre udskiftninger af jump-instruktioner (langspring erstattet af korte eller relative hop) i et vilkårligt antal pas efter anmodning. Andre kan endda foretage simpel omlægning eller indsættelse af instruktioner, f.eks. Nogle samlere til RISC -arkitekturer, der kan hjælpe med at optimere en fornuftig instruktionsplanlægning for at udnytte CPU -rørledningen så effektivt som muligt.
Assemblere har været tilgængelige siden 1950'erne, som det første trin over maskinsprog og før programmeringssprog på højt niveau som Fortran , Algol , COBOL og Lisp . Der har også været flere klasser af oversættere og halvautomatiske kodegeneratorer med egenskaber, der ligner både samling og sprog på højt niveau, med Speedcode som måske et af de mere kendte eksempler.
Der kan være flere montører med forskellig syntaks for en bestemt CPU eller instruktionssætarkitektur . For eksempel kan en instruktion om at tilføje hukommelsesdata til et register i en x86 -familieprocessor være add eax,[ebx]i original Intel -syntaks , hvorimod dette ville blive skrevet addl (%ebx),%eaxi AT & T -syntaksen, der bruges af GNU Assembler . På trods af forskellige udseende genererer forskellige syntaktiske former generelt den samme numeriske maskinkode . En enkelt assembler kan også have forskellige tilstande for at understøtte variationer i syntaktiske former såvel som deres nøjagtige semantiske fortolkninger (såsom FASM -syntax, TASM -syntax, idealtilstand osv. I det særlige tilfælde af x86 -samlingsprogrammering ).
Antal afleveringer
Der er to typer assemblere baseret på, hvor mange passager gennem kilden, der er nødvendige (hvor mange gange assembler læser kilden) for at producere objektfilen.
- One-pass montører går igennem kildekoden en gang. Ethvert symbol, der bruges, før det defineres, kræver "errata" i slutningen af objektkoden (eller i det mindste ikke tidligere end det punkt, hvor symbolet er defineret), der fortæller linkeren eller læsseren at "gå tilbage" og overskrive en pladsholder, der var blevet efterladt, hvor det endnu ikke definerede symbol blev brugt.
- Multipass-montører opretter en tabel med alle symboler og deres værdier i de første pas, og derefter bruger tabellen i senere pas til at generere kode.
I begge tilfælde skal samleren være i stand til at bestemme størrelsen af hver instruktion på de første pas for at beregne adresserne på efterfølgende symboler. Dette betyder, at hvis størrelsen på en operation, der henviser til en operand, der er defineret senere, afhænger af operandens type eller afstand, vil assembler foretage et pessimistisk skøn, når den første gang støder på operationen, og om nødvendigt putte den med et eller flere " nej " -operation "instruktioner i et senere pas eller errata. I en assembler med kighullsoptimering kan adresser genberegnes mellem passager for at muliggøre udskiftning af pessimistisk kode med kode, der er skræddersyet til den nøjagtige afstand fra målet.
Den oprindelige årsag til brugen af one-pass assemblers var hukommelsesstørrelse og monteringshastighed-ofte ville et andet pass kræve at gemme symboltabellen i hukommelsen (for at håndtere fremadrettede referencer ), spole tilbage og genlæse programkilden på bånd eller genlæse en dæk af kort eller hullet papir tape . Senere computere med meget større hukommelser (især diskopbevaring) havde plads til at udføre al nødvendig behandling uden sådan genlæsning. Fordelen ved multi-pass assembler er, at fraværet af errata gør forbindelsesprocessen (eller programindlæsning, hvis assembler direkte producerer eksekverbar kode) hurtigere.
Eksempel: i det følgende kodestykke ville en one-pass assembler være i stand til at bestemme adressen på den bagudgående reference BKWD ved samling af sætning S2 , men ville ikke være i stand til at bestemme adressen på den fremadrettede reference FWD ved samling af grenudtalelsen S1 ; faktisk kan FWD være udefineret. En topas-assembler ville bestemme begge adresser i pass 1, så de ville være kendt, når de genererer kode i pass 2.
S1 B FWD ... FWD EQU * ... BKWD EQU * ... S2 B BKWD
Montører på højt niveau
Mere sofistikerede montører på højt niveau giver sprogabstraktioner som:
- Procedure-/funktionserklæringer og påkaldelser på højt niveau
- Avancerede kontrolstrukturer (IF/THEN/ELSE, SWITCH)
- Abstrakte datatyper på højt niveau, herunder strukturer/poster, fagforeninger, klasser og sæt
- Sofistikeret makrobehandling (selvom den er tilgængelig på almindelige montører siden slutningen af 1950'erne til f.eks. IBM 700 -serien og IBM 7000 -serien og siden 1960'erne til blandt andet IBM System/360 (S/360))
- Objektorienterede programmeringsfunktioner såsom klasser , objekter , abstraktion , polymorfisme og arv
Se Sprogdesign herunder for flere detaljer.
Forsamlingssprog
Et program skrevet på samlingssprog består af en række mnemoniske processorinstruktioner og metasætninger (kendt som direktiver, pseudo-instruktioner og pseudo-ops), kommentarer og data. Samlingssprogsinstruktioner består normalt af en opcode -mnemonic efterfulgt af en operand , som kan være en liste over data, argumenter eller parametre. Nogle instruktioner kan være "underforståede", hvilket betyder, at de data, som instruktionen fungerer på, implicit defineres af selve instruktionen - sådan en instruktion tager ikke en operand. Den resulterende erklæring oversættes af en assembler til instruktioner i maskinsprog , der kan indlæses i hukommelsen og eksekveres.
For eksempel fortæller instruktionen herunder en x86 / IA-32- processor at flytte en øjeblikkelig 8-bit værdi ind i et register . Den binære kode for denne instruktion er 10110 efterfulgt af en 3-bit identifikator for hvilket register der skal bruges. Identifikatoren for AL -registret er 000, så følgende maskinkode indlæser AL -registret med dataene 01100001.
10110000 01100001
Denne binære computerkode kan gøres mere menneskelig læselig ved at udtrykke den i hexadecimal som følger.
B0 61
Her B0betyder 'Flyt en kopi af følgende værdi til AL og 61er en hexadecimal repræsentation af værdien 01100001, som er 97 i decimal . Monteringssprog for 8086 -familien giver mnemonisk MOV (en forkortelse af træk ) til instruktioner som denne, så maskinkoden ovenfor kan skrives som følger på samlingssprog, komplet med en forklarende kommentar, hvis det kræves, efter semikolonet. Dette er meget lettere at læse og huske.
MOV AL, 61h ; Load AL with 97 decimal (61 hex)
På nogle samlingssprog (inklusive dette) kan den samme hukommelsesniveau, såsom MOV, bruges til en familie af relaterede instruktioner til indlæsning, kopiering og flytning af data, uanset om det er umiddelbare værdier, værdier i registre eller hukommelsessteder, der peges på af værdier i registre eller ved umiddelbare (alias direkte) adresser. Andre montører kan bruge separate opcode -mnemonics som L til "flyt hukommelse til registrering", ST til "flyt register til hukommelse", LR til "flytte register til registrering", MVI for "flyt øjeblikkelig operand til hukommelse" osv.
Hvis den samme mnemonic bruges til forskellige instruktioner, betyder det, at mnemonic svarer til flere forskellige binære instruktionskoder, eksklusive data (f.eks. 61hI dette eksempel), afhængigt af de operander, der følger mnemonic. For eksempel for x86/IA-32 CPU'erne MOV AL, AHrepræsenterer Intel-samlingens sprogsyntaks en instruktion, der flytter indholdet af register AH til register AL . Den hexadecimale form af denne instruktion er:
88 E0
Den første byte, 88h, identificerer et træk mellem et byte-stort register og enten et andet register eller en hukommelse, og den anden byte, E0h, er kodet (med tre bitfelter) for at angive, at begge operander er registre, kilden er AH , og destinationen er AL .
I et tilfælde som dette, hvor den samme mnemonic kan repræsentere mere end en binær instruktion, bestemmer assembleren, hvilken instruktion der skal genereres ved at undersøge operanderne. I det første eksempel er operanden 61hen gyldig hexadecimal numerisk konstant og er ikke et gyldigt registernavn, så kun B0instruktionen kan være relevant. I det andet eksempel er operanden AHet gyldigt registernavn og ikke en gyldig numerisk konstant (hexadecimal, decimal, oktal eller binær), så kun 88instruktionen kan være relevant.
Samlingssprog er altid designet, så denne form for entydighed håndhæves universelt af deres syntaks. For eksempel i Intel x86 -samlingsproget skal en hexadecimal konstant starte med et ciffer, så det hexadecimale tal 'A' (lig med decimal ti) skrives som 0Aheller 0AHikke AH, specifikt, så det ikke ser ud til at være navnet på register AH . (Den samme regel forhindrer også tvetydighed med navnene på registrerne BH , CH og DH , samt med ethvert brugerdefineret symbol, der ender med bogstavet H og ellers kun indeholder tegn, der er hexadecimale cifre, f.eks. Ordet "STRAND ".)
Tilbage til det originale eksempel, mens x86 opcode 10110000 ( B0) kopierer en 8-bit værdi til AL- registret, flytter 10110001 ( B1) den til CL, og 10110010 ( B2) gør det til DL . Monteringssprogeksempler til disse følger.
MOV AL, 1h ; Load AL with immediate value 1
MOV CL, 2h ; Load CL with immediate value 2
MOV DL, 3h ; Load DL with immediate value 3
Syntaksen for MOV kan også være mere kompleks som de følgende eksempler viser.
MOV EAX, [EBX] ; Move the 4 bytes in memory at the address contained in EBX into EAX
MOV [ESI+EAX], CL ; Move the contents of CL into the byte at address ESI+EAX
MOV DS, DX ; Move the contents of DX into segment register DS
I hvert tilfælde oversættes MOV mnemonic direkte til en af opcodes 88-8C, 8E, A0-A3, B0-BF, C6 eller C7 af en assembler, og programmøren behøver normalt ikke at vide eller huske hvilken.
At omdanne samlingssprog til maskinkode er en montørs opgave, og det modsatte kan i det mindste delvist opnås ved en demonterer . I modsætning til sprog på højt niveau er der en en-til-en-overensstemmelse mellem mange enkle montagesætninger og maskinsprogsinstruktioner. I nogle tilfælde kan en montør imidlertid levere pseudoinstruktioner (i det væsentlige makroer), der udvides til flere maskinsprogsinstruktioner for at give almindeligt nødvendige funktioner. For eksempel, for en maskine, der mangler en "gren, hvis større eller lige" instruktion, kan en montør levere en pseudoinstruktion, der udvides til maskinens "sæt hvis mindre end" og "gren hvis nul (på resultatet af den angivne instruktion)" . De fleste fuldt udstyrede montører har også et rigt makrosprog (diskuteret nedenfor), som bruges af leverandører og programmører til at generere mere komplekse kode- og datasekvenser. Da oplysningerne om pseudoinstruktioner og makroer, der er defineret i assembler-miljøet, ikke er til stede i objektprogrammet, kan en demonterer ikke rekonstruere makro- og pseudoinstruktionskaldene, men kan kun adskille de faktiske maskininstruktioner, som assembleren genererede fra disse abstrakte samlingssprogede enheder. Da kommentarer i forsamlingens sprogkildefil ignoreres af samleren og ikke har nogen indvirkning på den objektkode, den genererer, er en afmonterer altid fuldstændig ude af stand til at gendanne kildekommentarer.
Hver computerarkitektur har sit eget maskinsprog. Computere adskiller sig i antallet og typen af operationer, de understøtter, i de forskellige størrelser og antal registre og i repræsentationer af data i lagring. Selvom de fleste computere til almindelige formål i det væsentlige kan udføre den samme funktionalitet, er måderne, hvorpå de gør det, forskellige; de tilsvarende forsamlingssprog afspejler disse forskelle.
Der kan eksistere flere sæt mnemonics eller samlingssprogssyntaks for et enkelt instruktionssæt, der typisk instantieres i forskellige assembler-programmer. I disse tilfælde er den mest populære normalt den, der leveres af CPU -producenten og bruges i dens dokumentation.
To eksempler på CPU'er, der har to forskellige sæt mnemonics, er Intel 8080 -familien og Intel 8086/8088. Fordi Intel hævdede ophavsret til dets monteringssprogmnemonik (på hver side i deres dokumentation, der blev offentliggjort i 1970'erne og begyndelsen af 1980'erne, i det mindste), opfandt nogle virksomheder, der uafhængigt producerede CPU'er, der er kompatible med Intel -instruktionssæt, deres egne mnemonics. Den Zilog Z80 CPU, en forbedring af Intel 8080A , understøtter alle de 8080A instruktioner plus mange flere; Zilog opfandt et helt nyt samlingssprog, ikke kun for de nye instruktioner, men også for alle 8080A -instruktionerne. For eksempel, hvor Intel bruger mnemonics MOV , MVI , LDA , STA , LXI , LDAX , STAX , LHLD og SHLD til forskellige dataoverførselsinstruktioner, bruger Z80 -samlingsproget det mnemoniske LD for dem alle. En lignende sag er NEC V20 og V30 CPU'er, forbedrede kopier af henholdsvis Intel 8086 og 8088. Ligesom Zilog med Z80 opfandt NEC nye mnemonics for alle 8086 og 8088 instruktionerne for at undgå beskyldninger om krænkelse af Intels ophavsret. (Det er tvivlsomt, om sådanne ophavsrettigheder kan være gyldige, og senere genudgav CPU-virksomheder som AMD og Cyrix Intels x86/IA-32 instruktionsmnemonik nøjagtigt med hverken tilladelse eller juridisk straf.) Det er tvivlsomt, om det i praksis var mange mennesker, der programmerede V20 og V30 skrev faktisk på NECs samlingssprog frem for Intels; da to samlingssprog for samme instruktionssætarkitektur er isomorfe (lidt som engelsk og svinelatin ), er der ikke krav om at bruge en producents eget publicerede samlingssprog med producentens produkter.
Sprogdesign
Grundlæggende elementer
Der er en stor grad af mangfoldighed i den måde, forfatterne af montører kategoriserer udsagn og i den nomenklatur, de bruger. Nogle beskriver især alt andet end en maskine mnemonic eller udvidet mnemonic som en pseudo-operation (pseudo-op). Et typisk samlingssprog består af 3 typer instruktionserklæringer, der bruges til at definere programoperationer:
- Opcode mnemonics
- Datadefinitioner
- Monteringsdirektiver
Opcode mnemonics og udvidede mnemonics
Instruktioner (udsagn) på samlingssprog er generelt meget enkle, i modsætning til dem på sprog på højt niveau . Generelt er en mnemonic et symbolsk navn på en enkelt eksekverbar maskinsprogsinstruktion (en opcode ), og der er mindst én opcode -mnemonic defineret for hver maskinesprogsinstruktion. Hver instruktion består typisk af en operation eller opcode plus nul eller flere operander . De fleste instruktioner refererer til en enkelt værdi eller et par værdier. Operander kan være umiddelbare (værdi kodet i selve instruktionen), registre specificeret i instruktionen eller underforstået, eller adresserne til data placeret andre steder i lageret. Dette bestemmes af den underliggende processorarkitektur: samleren afspejler blot, hvordan denne arkitektur fungerer. Udvidede mnemonics bruges ofte til at angive en kombination af en opcode med en bestemt operand, f.eks. System/360 -assemblerne bruger Bsom en udvidet hukommelsesteknik til BCmed en maske på 15 og NOP("INGEN OPERATION" - gør ikke noget for et trin) for BCmed en maske på 0.
Udvidede mnemonics bruges ofte til at understøtte specialiseret brug af instruktioner, ofte til formål, der ikke fremgår af instruktionsnavnet. For eksempel har mange CPU'er ikke en eksplicit NOP -instruktion, men har instruktioner, der kan bruges til formålet. I 8086 CPU'er bruges instruktionen til , idet det er en pseudo-opcode til kodning af instruktionen . Nogle adskillere genkender dette og vil afkode instruktionen som . På samme måde bruger IBM -montører til System/360 og System/370 den udvidede mnemonik og til og med nul masker. For SPARC -arkitekturen kaldes disse syntetiske instruktioner .
xchg ax,axnopnopxchg ax,axxchg ax,axnopNOPNOPRBCBCR
Nogle montører understøtter også enkle indbyggede makroinstruktioner, der genererer to eller flere maskininstruktioner. For eksempel er det med nogle Z80 -samlere ld hl,bcanerkendt at instruktionen genererer ld l,cefterfulgt af ld h,b. Disse er undertiden kendt som pseudo-opcodes .
Mnemonics er vilkårlige symboler; I 1985 offentliggjorde IEEE Standard 694 for et ensartet sæt mnemonics, der skal bruges af alle montører. Standarden er siden blevet trukket tilbage.
Datadirektiver
Der er instruktioner, der bruges til at definere dataelementer til lagring af data og variabler. De definerer datatypen, længden og tilpasningen af data. Disse instruktioner kan også definere, om dataene er tilgængelige for eksterne programmer (programmer samlet separat) eller kun for det program, hvor datasektionen er defineret. Nogle montører klassificerer disse som pseudo-ops.
Monteringsdirektiver
Monteringsdirektiver, også kaldet pseudo-opcodes, pseudo-operationer eller pseudo-ops, er kommandoer, der gives til en samler "der pålægger den at udføre andre operationer end samleinstruktioner". Direktiver påvirker, hvordan assembler fungerer, og "kan påvirke objektkoden, symboltabellen, noteringsfilen og værdierne for interne assembler -parametre". Nogle gange er udtrykket pseudo-opcode forbeholdt direktiver, der genererer objektkode, f.eks. Dem, der genererer data.
Navnene på pseudo-ops starter ofte med en prik for at skelne dem fra maskininstruktioner. Pseudo-ops kan gøre samlingen af programmet afhængig af parametre indtastet af en programmør, så et program kan samles på forskellige måder, måske til forskellige applikationer. Eller en pseudo-op kan bruges til at manipulere præsentationen af et program for at gøre det lettere at læse og vedligeholde. En anden almindelig brug af pseudo-ops er at reservere lagerområder til data i løbetid og eventuelt initialisere deres indhold til kendte værdier.
Symboliske samlere lader programmører forbinde vilkårlige navne ( etiketter eller symboler ) med hukommelsessteder og forskellige konstanter. Normalt får hver konstant og variabel et navn, så instruktioner kan henvise til disse steder ved navn og dermed fremme selvdokumenterende kode . I eksekverbar kode er navnet på hver underrutine forbundet med dets indgangspunkt, så alle opkald til en underprogram kan bruge dets navn. Inde i underrutiner får GOTO -destinationer etiketter. Nogle samlere understøtter lokale symboler, som ofte leksikalt adskiller sig fra normale symboler (f.eks. Brug af "10 $" som en GOTO -destination).
Nogle montører, såsom NASM , giver fleksibel symbolstyring, lader programmører styre forskellige navneområder , beregner automatisk forskydninger inden for datastrukturer og tildeler etiketter, der refererer til bogstavelige værdier eller resultatet af simple beregninger udført af samleren. Etiketter kan også bruges til at initialisere konstanter og variabler med adresser, der kan flyttes.
Samlingssprog, ligesom de fleste andre computersprog, tillader, at kommentarer tilføjes til programmets kildekode, der ignoreres under samlingen. Omhyggelig kommentar er afgørende i montagesprogsprogrammer, da betydningen og formålet med en sekvens af binære maskininstruktioner kan være svært at bestemme. Det "rå" (ukommenterede) samlingssprog, der genereres af kompilatorer eller adskillere, er ret vanskeligt at læse, når der skal foretages ændringer.
Makroer
Mange montører understøtter foruddefinerede makroer , og andre understøtter programmeringsdefinerede (og gentagne gange omdefinerbare) makroer, der involverer sekvenser af tekstlinjer, hvor variabler og konstanter er integreret. Makrodefinitionen er oftest en blanding af assembler -sætninger, f.eks. Direktiver, symbolske maskininstruktioner og skabeloner til assembler -udsagn. Denne sekvens af tekstlinjer kan omfatte opcodes eller direktiver. Når en makro er blevet defineret, kan dens navn bruges i stedet for en mnemonic. Når samleren behandler en sådan sætning, erstatter den sætningen med de tekstlinjer, der er knyttet til den pågældende makro, og behandler dem derefter, som om de eksisterede i kildekodefilen (herunder i nogle samlere udvidelse af eventuelle makroer, der findes i erstatningsteksten) . Makroer i denne forstand dateres til IBM autokodere fra 1950'erne.
I samlingssprog repræsenterer udtrykket "makro" et mere omfattende koncept, end det gør i nogle andre sammenhænge, f.eks. Forprocessoren i programmeringssproget C , hvor dets #define-direktiv typisk bruges til at oprette korte enkeltlinjemakroer. Assembler -makroinstruktioner, ligesom makroer i PL/I og nogle andre sprog, kan være langvarige "programmer" af sig selv, udført ved fortolkning af assembler under samling.
Da makroer kan have 'korte' navne, men kan udvides til flere eller faktisk mange linjer med kode, kan de bruges til at få samlingsprogrammer til at se ud til at være langt kortere, hvilket kræver færre linjer med kildekode, som med sprog på højere niveau. De kan også bruges til at tilføje højere niveauer af struktur til samlingsprogrammer, eventuelt indføre integreret fejlretningskode via parametre og andre lignende funktioner.
Makrosamlere tillader ofte makroer at tage parametre . Nogle samlere inkluderer ganske sofistikerede makro sprog, der indeholder sådanne sproglige elementer på højt niveau som valgfrie parametre, symbolske variabler, betingelser, strengmanipulation og aritmetiske operationer, der alle kan bruges under udførelsen af en given makro og tillader makroer at gemme kontekst eller udveksle oplysninger . Således kan en makro generere mange samlingssprogsinstruktioner eller datadefinitioner baseret på makroargumenterne. Dette kan f.eks. Bruges til at generere datastrukturer i poststil eller " afrullede " sløjfer eller kunne generere hele algoritmer baseret på komplekse parametre. For eksempel kan en "sorterings" makro acceptere specifikationen for en kompleks sorteringsnøgle og generere kode, der er udformet til den specifikke nøgle, uden at have brug for de kørselstidstests, der ville være nødvendige for en generel procedure, der fortolker specifikationen. En organisation, der bruger samlingssprog, der er blevet kraftigt udvidet ved hjælp af en sådan makro-suite, kan anses for at arbejde på et sprog på højere niveau, da sådanne programmører ikke arbejder med en computers laveste niveau konceptuelle elementer. Understreget dette punkt blev makroer brugt til at implementere en tidlig virtuel maskine i SNOBOL4 (1967), som blev skrevet i SNOBOL Implementation Language (SIL), et samlingssprog til en virtuel maskine. Målmaskinen ville oversætte dette til sin native kode ved hjælp af en makro -assembler . Dette tillod en høj grad af transportabilitet for tiden.
Makroer blev brugt til at tilpasse store softwaresystemer til bestemte kunder i mainframe -æraen og blev også brugt af kundens personale til at tilfredsstille deres arbejdsgivers behov ved at lave specifikke versioner af producentens operativsystemer. Dette blev f.eks. Udført af systemprogrammører, der arbejder med IBM 's Conversational Monitor System / Virtual Machine ( VM / CMS ) og med IBM's tilføjelser til "real-time transaktionsbehandling", Customer Information Control System CICS og ACP / TPF , flyselskabet/det finansielle system, der begyndte i 1970'erne og stadig driver mange store computerreservationssystemer (CRS) og kreditkortsystemer i dag.
Det er også muligt at udelukkende bruge en assemblers makrobehandlingsevner til at generere kode skrevet på helt forskellige sprog, for eksempel til at generere en version af et program i COBOL ved hjælp af et rent makro -assembler -program, der indeholder linjer med COBOL -kode inde i samlings -tid -operatører instruere samleren til at generere vilkårlig kode. IBM OS/360 bruger makroer til at udføre systemgenerering . Brugeren angiver muligheder ved at kode en række assembler -makroer. Ved at samle disse makroer genereres en jobstrøm til at bygge systemet, herunder sprog til jobkontrol og værktøjskontrolerklæringer .
Dette skyldes, at begrebet "makrobehandling", som blev realiseret i 1960'erne, er uafhængigt af begrebet "samling", idet førstnævnte i moderne termer er mere tekstbehandling, tekstbehandling, end at generere objektkode. Begrebet makrobehandling dukkede op og vises i programmeringssproget C, der understøtter "forprocessorinstruktioner" til at indstille variabler og foretage betingede tests af deres værdier. I modsætning til visse tidligere makroprocessorer inde i assemblere er C-preprocessoren ikke Turing-komplet, fordi den mangler evnen til enten at loop eller "gå til", sidstnævnte tillader programmer at loop.
På trods af makroforarbejdningens kraft faldt den i ubrug på mange sprog på højt niveau (store undtagelser er C , C ++ og PL/I), mens den stadig var en flerårig for samlere.
Makroparameterudskiftning er strengt ved navn: ved makrobehandlingstid erstattes værdien af en parameter tekstvist med dens navn. Den mest berømte klasse af fejl, der var resultatet, var brugen af en parameter, der i sig selv var et udtryk og ikke et simpelt navn, når makroforfatteren forventede et navn. I makroen:
foo: macro a load a*b
hensigten var, at den, der ringede, skulle angive navnet på en variabel, og den "globale" variabel eller konstant b ville blive brugt til at gange "a". Hvis foo kaldes med parameteren a-c, load a-c*bsker makroudvidelsen af . For at undgå enhver tvetydighed kan brugere af makroprocessorer parentesere formelle parametre inde i makrodefinitioner, eller opkaldere kan parentesere inputparametrene.
Understøttelse af struktureret programmering
Der er skrevet pakker med makroer, der giver strukturerede programmeringselementer til at kode eksekveringsstrømmen. Det tidligste eksempel på denne fremgangsmåde var i Concept-14-makrosættet , oprindeligt foreslået af Harlan Mills (marts 1970), og implementeret af Marvin Kessler ved IBM's Federal Systems Division, som leverede IF/ELSE/ENDIF og lignende kontrolflowblokke til OS /360 assembler -programmer. Dette var en måde at reducere eller eliminere brugen af GOTO -operationer i samlingskode, en af de vigtigste faktorer, der forårsagede spaghettikode i samlingssprog. Denne fremgangsmåde blev bredt accepteret i begyndelsen af 1980'erne (de sidste dage med storstilet samling af sprogbrug). IBM's High Level Assembler Toolkit indeholder en sådan makropakke.
Et nysgerrigt design var A-natural , en " strømorienteret " assembler til 8080/ Z80 , processorer fra Whitesmiths Ltd. (udviklere af Unix- lignende Idris- operativsystem, og det blev rapporteret at være den første kommercielle C- kompilator ). Sproget blev klassificeret som en assembler, fordi det fungerede med rå maskinelementer såsom opcodes , registre og hukommelsesreferencer; men det inkorporerede en udtrykssyntaks for at angive udførelsesrækkefølge. Parenteser og andre specielle symboler kontrollerede sammen med blokorienterede strukturerede programmeringskonstruktioner sekvensen af de genererede instruktioner. A-natural blev bygget som objektsprog for en C-kompilator, snarere end til håndkodning, men dens logiske syntaks vandt nogle fans.
Der har været ringe efterspørgsel efter mere sofistikerede montører siden faldet i udviklingen af den store samling af sprog. På trods af det bliver de stadig udviklet og anvendt i tilfælde, hvor ressourcebegrænsninger eller særegenheder i målsystemets arkitektur forhindrer effektiv brug af sprog på højere niveau.
Assemblere med en stærk makromotor tillader struktureret programmering via makroer, f.eks. Switch -makroen, der følger med Masm32 -pakken (denne kode er et komplet program):
include \masm32\include\masm32rt.inc ; use the Masm32 library
.code
demomain:
REPEAT 20
switch rv(nrandom, 9) ; generate a number between 0 and 8
mov ecx, 7
case 0
print "case 0"
case ecx ; in contrast to most other programming languages,
print "case 7" ; the Masm32 switch allows "variable cases"
case 1 .. 3
.if eax==1
print "case 1"
.elseif eax==2
print "case 2"
.else
print "cases 1 to 3: other"
.endif
case 4, 6, 8
print "cases 4, 6 or 8"
default
mov ebx, 19 ; print 20 stars
.Repeat
print "*"
dec ebx
.Until Sign? ; loop until the sign flag is set
endsw
print chr$(13, 10)
ENDM
exit
end demomain
Brug af samlingssprog
Historisk perspektiv
Samlingssprog var ikke tilgængelige på det tidspunkt, da den lagrede programcomputer blev introduceret. Kathleen Booth "krediteres med at opfinde forsamlingssprog" baseret på teoretisk arbejde, hun begyndte i 1947, mens hun arbejdede med ARC2 på Birkbeck, University of London efter konsultation af Andrew Booth (senere hendes mand) med matematiker John von Neumann og fysiker Herman Goldstine på den Institute for Advanced Study .
I slutningen af 1948 havde Electronic Delay Storage Automatic Calculator (EDSAC) en assembler (kaldet "indledende ordrer") integreret i sit bootstrap -program. Det brugte en-bogstavet hukommelsesteknik udviklet af David Wheeler , der er krediteret af IEEE Computer Society som skaberen af den første "assembler". Rapporter om EDSAC introducerede udtrykket "samling" for processen med at kombinere felter til et instruktionsord. SOAP ( Symbolic Optimal Assembly Program ) var et samlingssprog til IBM 650 -computeren skrevet af Stan Poley i 1955.
Monteringssprog eliminerer meget af den fejlbehæftede, kedelige og tidskrævende førstegenerationsprogrammering, der er nødvendig med de tidligste computere, og frigør programmerere fra kedelighed, såsom at huske numeriske koder og beregne adresser.
Samlingssprog blev engang meget udbredt til alle former for programmering. Men i 1980'erne (1990'erne på mikrocomputere ) var deres anvendelse stort set blevet fortrængt af sprog på højere niveau i søgen efter forbedret programmeringsproduktivitet . I dag bruges forsamlingssprog stadig til direkte hardware manipulation, adgang til specialiserede processorinstruktioner eller til at løse kritiske ydelsesproblemer. Typiske anvendelser er enhedsdrivere , integrerede systemer på lavt niveau og systemer i realtid .
Historisk set er mange programmer udelukkende skrevet i samlingssprog. Den Burroughs MCP (1961) var den første computer, for hvilken et operativsystem ikke blev udviklet helt i assembler; den blev skrevet i Executive Systems Problem Oriented Language (ESPOL), en Algol -dialekt. Mange kommercielle applikationer blev også skrevet på montagesprog, herunder en stor mængde IBM -mainframe -software skrevet af store virksomheder. COBOL , FORTRAN og nogle PL/I fortrængte til sidst meget af dette arbejde, selvom en række store organisationer beholdt montagesprogede applikationsinfrastrukturer langt ind i 1990'erne.
De fleste tidlige mikrocomputere stolede på håndkodet samlingssprog, herunder de fleste operativsystemer og store applikationer. Dette var fordi disse systemer havde alvorlige ressourcebegrænsninger, pålagde idiosynkratiske hukommelses- og displayarkitekturer og leverede begrænsede, buggy systemtjenester. Måske vigtigere var manglen på førsteklasses sprogkompilatorer, der er velegnede til brug af mikrocomputere. En psykologisk faktor kan også have spillet en rolle: den første generation af mikrocomputer -programmerere bevarede en hobbyist, "ledninger og tang" -holdning.
I en mere kommerciel kontekst var de største grunde til at bruge samlingssprog minimal oppustethed (størrelse), minimal overhead, større hastighed og pålidelighed.
Typiske eksempler på store samling sprogprogrammer fra denne tid er IBM PC DOS -operativsystemer, det Turbo Pascal compiler og begyndelsen af applikationer såsom regneark programmet Lotus 1-2-3 . Monteringssprog blev brugt til at få den bedste ydelse ud af Sega Saturn , en konsol, der var notorisk udfordrende at udvikle og programmere spil til. Arkadespillet NBA Jam fra 1993 er et andet eksempel.
Monteringssprog har længe været det primære udviklingssprog for mange populære hjemmecomputere i 1980'erne og 1990'erne (såsom MSX , Sinclair ZX Spectrum , Commodore 64 , Commodore Amiga og Atari ST ). Dette var i høj grad fordi fortolkede BASIC -dialekter på disse systemer tilbød utilstrækkelig udførelseshastighed samt utilstrækkelige faciliteter til at drage fuld fordel af den tilgængelige hardware på disse systemer. Nogle systemer har endda et integreret udviklingsmiljø (IDE) med meget avancerede fejlfindings- og makrofaciliteter. Nogle kompilatorer til rådighed for Radio Shack TRS-80 og dens efterfølgere havde evnen til at kombinere inline-samlingskilde med programudsagn på højt niveau. Ved kompilering producerede en indbygget assembler inline maskinkode.
Nuværende brug
Der har altid været debatter om nytten og ydelsen af samlingssprog i forhold til sprog på højt niveau.
Selvom samlingssprog har specifikke nicheanvendelser, hvor det er vigtigt (se nedenfor), er der andre værktøjer til optimering.
I juli 2017 rangerer TIOBE -indekset for programmeringssprogs popularitet forsamlingssprog til 11, f.eks. Foran Visual Basic . Assembler kan bruges til at optimere til hastighed eller optimere til størrelse. I tilfælde af hastighedsoptimering hævdes moderne optimeringskompilatorer at lave sprog på højt niveau til kode, der kan køre lige så hurtigt som håndskrevet samling, på trods af de modeksempler, der kan findes. Kompleksiteten af moderne processorer og hukommelsessubsystemer gør effektiv optimering stadig vanskeligere for kompilatorer såvel som for montageprogrammører. Desuden har øget processorydelse betydet, at de fleste CPU'er sidder inaktive det meste af tiden, med forsinkelser forårsaget af forudsigelige flaskehalse som f.eks. Cache -fejl, I/O -operationer og personsøgning . Dette har gjort, at hurtig kodeudførelse er et ikke-problem for mange programmører.
Der er nogle situationer, hvor udviklere kan vælge at bruge samlingssprog:
- Skrivningskode til systemer med ældre processorer, der har begrænsede sprogindstillinger på højt niveau, f.eks. Atari 2600 , Commodore 64 og grafregnere . Programmer til disse computere fra 1970'erne og 1980'erne er ofte skrevet i forbindelse med demoscene eller retrogaming subkulturer.
- Kode, der skal interagere direkte med hardwaren, f.eks. I enhedsdrivere og afbrydere .
- I en integreret processor eller DSP kræver afbrydelser med høj gentagelse det korteste antal cyklusser pr. Afbrydelse, f.eks. En afbrydelse, der sker 1000 eller 10000 gange i sekundet.
- Programmer, der skal bruge processorspecifikke instruktioner, der ikke er implementeret i en compiler. Et almindeligt eksempel er den bitvise rotationsinstruktion i kernen af mange krypteringsalgoritmer, samt forespørgsel efter pariteten af en byte eller 4-bit carry af en tilføjelse.
- En enkeltstående eksekverbar fil med kompakt størrelse er påkrævet, som skal eksekveres uden brug af driftstidskomponenter eller biblioteker, der er knyttet til et sprog på højt niveau. Eksempler har omfattet firmware til telefoner, bilbrændstof- og tændingssystemer, klimaanlæg, sikkerhedssystemer og sensorer.
- Programmer med præstationsfølsomme indre sløjfer, hvor samlesprog giver optimeringsmuligheder, der er svære at opnå på et sprog på højt niveau. For eksempel lineær algebra med BLAS eller diskret cosinustransformation (f.eks. SIMD -forsamlingsversion fra x264 ).
- Programmer, der opretter vektoriserede funktioner til programmer på sprog på højere niveau, f.eks. C. På sprog på højere niveau understøttes dette undertiden af kompilatorens iboende funktioner, der kortlægges direkte til SIMD-mnemonik, men ikke desto mindre resulterer i en en-til-en-konverteringskonverteringsspecifik for den givne vektorprocessor.
- Realtidsprogrammer såsom simuleringer, flynavigationssystemer og medicinsk udstyr. For eksempel i et fly-by-wire- system skal telemetri tolkes og ageres inden for strenge tidsbegrænsninger. Sådanne systemer skal eliminere kilder til uforudsigelige forsinkelser, som kan være skabt af (nogle) fortolkede sprog, automatisk indsamling af skrald , personsøgningsoperationer eller præventiv multitasking . Nogle sprog på højere niveau indeholder imidlertid komponenter i driftstid og operativsystemgrænseflader, der kan indføre sådanne forsinkelser. Valg af samling eller sprog på lavere niveau til sådanne systemer giver programmører større synlighed og kontrol over behandlingsdetaljer.
- Kryptografiske algoritmer, der altid skal tage nøjagtig samme tid at udføre, hvilket forhindrer tidsangreb .
- Rediger og udvid den ældre kode, der er skrevet til IBM -mainframe -computere.
- Situationer, hvor der kræves fuldstændig kontrol over miljøet, i situationer med ekstremt høj sikkerhed, hvor intet kan tages for givet .
- Computervirus , bootloadere , visse enhedsdrivere eller andre ting meget tæt på hardware eller operativsystem på lavt niveau.
- Instruktionssimulatorer til overvågning, sporing og fejlfinding, hvor yderligere omkostninger holdes på et minimum.
- Situationer, hvor der ikke findes noget sprog på højt niveau, på en ny eller specialiseret processor, som der ikke er nogen cross-compiler til rådighed for.
-
Reverse-engineering og ændring af programfiler, såsom:
- eksisterende binære filer, som måske oprindeligt er skrevet på et højt niveau, f.eks. når du forsøger at genskabe programmer, som kildekoden ikke er tilgængelig for, eller som er gået tabt, eller krakning af kopibeskyttelse af proprietær software.
- Videospil (også kaldet ROM -hacking ), hvilket er muligt via flere metoder. Den mest anvendte metode er ændring af programkode på samlingssprogsniveau.
Samlingssprog undervises stadig i de fleste datalogiske og elektroniske ingeniørprogrammer . Selvom få programmerere i dag regelmæssigt arbejder med samlingssprog som et værktøj, er de underliggende begreber fortsat vigtige. Sådanne fundamentale emner som binær aritmetik , hukommelse tildeling , stak behandling , tegnsæt kodning, afbryder behandling, og compiler design ville være svært at studere i detaljer uden en forståelse af, hvordan en computer fungerer på hardware-niveau. Da en computers adfærd grundlæggende er defineret af dets instruktionssæt, er den logiske måde at lære sådanne begreber at studere et samlingssprog. De fleste moderne computere har lignende instruktionssæt. Derfor er det tilstrækkeligt at studere et enkelt forsamlingssprog til at lære: I) de grundlæggende begreber; II) at genkende situationer, hvor brugen af samlingssprog kan være passende og III) for at se, hvor effektiv eksekverbar kode kan oprettes fra sprog på højt niveau.
Typiske applikationer
- Samlingssprog bruges typisk i et systems opstartskode , lavniveau-koden, der initialiserer og tester systemhardwaren før opstart af operativsystemet og ofte gemmes i ROM . ( BIOS på IBM-kompatible pc- systemer og CP/M er et eksempel.)
- Samlingssprog bruges ofte til kode på lavt niveau, f.eks. Til operativsystemkerner , som ikke kan stole på tilgængeligheden af allerede eksisterende systemopkald og faktisk skal implementere dem for den særlige processorarkitektur, som systemet vil køre på.
- Nogle kompilatorer oversætter sprog på højt niveau til samling først, før de kompileres fuldstændigt, så samlingskoden kan ses til fejlfinding og optimering.
- Nogle kompilatorer til relativt lave sprog, f.eks. Pascal eller C , gør det muligt for programmereren at integrere samlingssprog direkte i kildekoden (såkaldt inline-samling ). Programmer, der bruger sådanne faciliteter, kan derefter konstruere abstraktioner ved hjælp af forskellige samlingssprog på hver hardware -platform. Systemets bærbare kode kan derefter bruge disse processorspecifikke komponenter gennem en ensartet grænseflade.
- Monteringssprog er nyttigt i reverse engineering . Mange programmer distribueres kun i maskinkodeform, der er ligetil at oversætte til samlingssprog af en demonterer , men vanskeligere at oversætte til et sprog på et højere niveau via en dekompilator . Værktøjer som Interactive Disassembler gør omfattende brug af demontering til et sådant formål. Denne teknik bruges af hackere til at knække kommerciel software og konkurrenter til at producere software med lignende resultater fra konkurrerende virksomheder.
- Monteringssprog bruges til at øge udførelseshastigheden, især i tidlige personlige computere med begrænset processorkraft og RAM.
- Assemblere kan bruges til at generere blokke af data, uden sproglig overhead på højt niveau, fra formateret og kommenteret kildekode, der skal bruges af anden kode.
Se også
- Kompilator
- Sammenligning af montører
- Demonterer
- Hexadecimal
- Instruktionssæt arkitektur
- Lille mand computer -en uddannelsesmæssig computermodel med et basis-10 samlingssprog
- Nibble
- Skrevet samlingssprog
Noter
Referencer
Yderligere læsning
- Bartlett, Jonathan (2004). Programmering fra bunden - En introduktion til programmering ved hjælp af linux -montagesprog . Bartlett Publishing . ISBN 0-9752838-4-7. Arkiveret fra originalen 2020-03-24 . Hentet 2020-03-24 . [4]
- Britton, Robert (2003). MIPS Assembly Language Programming . Prentice Hall . ISBN 0-13-142044-5.
- Calingaert, Peter (1979) [1978-11-05]. Skrevet ved University of North Carolina at Chapel Hill . Horowitz, Ellis (red.). Assemblere, kompilatorer og programoversættelse . Computersoftware -serie (1. tryk, 1. udgave). Potomac, Maryland, USA: Computer Science Press, Inc. ISBN 0-914894-23-4. ISSN 0888-2088 . LCCN 78-21905 . Hentet 2020-03-20 . (2+xiv+270+6 sider)
- Duntemann, Jeff (2000). Monteringssprog trin for trin . Wiley . ISBN 0-471-37523-3.
- Kann, Charles W. (2015). "Introduktion til MIPS Assembly Language Programming" . Arkiveret fra originalen 2020-03-24 . Hentet 2020-03-24 .
- Kann, Charles W. (2021). " Introduktion til samlingsprogrammering: Fra suppe til nødder: ARM -udgave "
- Norton, Peter ; Socha, John (1986). Peter Nortons Assembly Language Book til IBM PC . New York, USA: Brady Books.
- Sanger, Michael (1980). PDP-11. Assembler Language Programming og Machine Organization . New York, USA: John Wiley & Sons .
- Sweetman, Dominic (1999). Se MIPS Run . Morgan Kaufmann Forlag . ISBN 1-55860-410-3.
- Waldron, John (1998). Introduktion til RISC Assembly Language Programming . Addison Wesley . ISBN 0-201-39828-1.
- Yurichev, Dennis (2020-03-04) [2013]. "Forstå montagesprog (Reverse Engineering for Beginners)" (PDF) . Arkiveret (PDF) fra originalen 2020-03-24 . Hentet 2020-03-24 .
- "ASM Community Book" . 2009. Arkiveret fra originalen 2013-05-30 . Hentet 2013-05-30 . ("En online bog fuld af nyttig ASM -info, selvstudier og kodeeksempler" af ASM -fællesskabet, arkiveret på internetarkivet.)
eksterne links
- Forsamlingssprog på Curlie
- Unix Assembly Language Programming
- Linux forsamling
- PPR: Learning Assembly Language
- NASM - The Netwide Assembler (et populært montagesprog)
- Eksempler på programmeringssprogsprogrammer
- Oprettelse af Windows -programmer på forsamlingssprog
- Monteringsoptimeringstip af Mark Larson
- Tabellen til samlingssprog til maskinkode