- Assemblerspråk organiserer instruksjonene sine etter formål: overføring, beregning, flytkontroll og mer.
- Hver instruksjon består av en opkode og operander, med forskjellige formater avhengig av arkitekturen.
- Det finnes flere adresseringsmåter for å få tilgang til data, for eksempel umiddelbar, direkte og indirekte.
Assemblerspråk har vært en av de grunnleggende søylene i programvareutvikling siden begynnelsen av databehandling. Selv om høynivåspråk dominerer scenen i dag, er assembler fortsatt mye brukt og relevant i miljøer der maskinvarekontroll, optimalisering eller ressursbegrensninger er en prioritet.
I denne artikkelen skal vi dykke ned i ulike typer instruksjoner for assemblerspråk, analysere strukturen, formålet, adresseringsmodusene og hvordan de er organisert på tvers av ulike arkitekturer. Du finner også eksempler, formater og en omfattende oversikt som lar deg forstå logikken bak disse instruksjonene, som fungerer tett sammen med maskinvaren.
Hva er en instruksjon i assemblerspråk?
En assemblerinstruksjon er en kommando som CPU-en kan forstå direkte (når den er oversatt til maskinkode av et assemblerprogram). Hver instruksjon har et spesifikt formål og består vanligvis av en mnemonisk kode som representerer operasjonen og en eller flere operander som indikerer hvor dataene hentes og/eller hvor resultatene lagres.
Disse instruksjonene er svært avhengige av prosessorarkitekturen, så hver type CPU (enten x86, ARM, MIPS, blant andre) har sitt eget sett med instruksjoner med spesifikk syntaks og funksjoner.
Strukturen til en instruksjon
Instruksjoner består vanligvis av to deler:
- Operasjonkode (opcode): Angir handlingen som skal utføres, som å legge til, flytte data, sammenligne osv.
Operander gir informasjonen som er nødvendig for å utføre operasjonen, og kan lagres i registre, minne eller være konstanter. Ikke alle instruksjoner krever operander, og i noen tilfeller kan disse være implisitt i instruksjonen eller lagret i forhåndsdefinerte registre.
Typer instruksjoner i assemblerspråk
Avhengig av funksjonaliteten de utfører i et program, kan instruksjoner for assemblerspråk klassifiseres i flere grupper. De mest relevante er beskrevet nedenfor:
1. Instruksjoner for dataoverføring
Disse instruksjonene gjør det mulig å kopiere data fra ett sted til et annet uten å endre innholdet ved kilden. De er viktige for å flytte informasjon mellom registre, minne og periferiutstyr.
Noen av de vanligste instruksjonene i denne gruppen er:
- MOV: Kopierer innholdet i én operand til en annen. For eksempel,
MOV AX, BXKopier innholdet fra BX til AX. - MOVS / MOVSB / MOVSW: Flytter strenger fra en kildeadresse (SI) til en destinasjonsadresse (DI), og automatiserer overføringsprosessen.
- LODS / LODSB / LODSW: Laster inn en verdi fra adressen angitt av SI-registeret i akkumulatoren (AL eller AX).
- LESE: Laster inn en effektiv adresse i stedet for verdien. Nyttig for å hente adressen til en variabel eller struktur.
2. Batteriinstruksjoner
Stakken er en LIFO-struktur (sist inn, først ut) som brukes til å midlertidig lagre data, sende parametere eller lagre utførelseskonteksten.
- TRYKK: Lagrer en verdi på stakken, og reduserer SP-pekeren.
- POP: Henter den nyeste verdien som er lagret på stakken, og øker SP.
- SKYV / POPF: De lagrer og henter tilstanden til CPU-flaggene på stakken.
3. Aritmetiske og logiske instruksjoner
De tillater utførelse av beregninger og operasjoner på biter. Disse instruksjonene er viktige for å manipulere numeriske data og ta beslutninger i programflyten.
Blant de mest brukte finner vi:
- LEGG TIL / UNDER: Addisjon og subtraksjon.
- MUL / IMUL: Binære multiplikasjoner.
- DIV / IDIV: Divisjon (heltall eller fortegn).
- OG / ELLER / XELLER / IKKE: Bitvise logiske operasjoner.
- SHL / SHR / ROL / ROR: Bitskift og rotasjoner.
4. Instruksjoner for flytkontroll
De lar deg endre programmets utførelsessekvens , introdusere hopp eller betingede og ubetingede kall til andre instruksjoner.
- JMP: Hopper ubetinget til en annen adresse i programmet.
- RING / RET: Kall til en subrutine og returner.
- JE/JNE/JG/JL/JZ/JNZ: Betingede hopp, de utføres hvis visse betingelser er oppfylt (etter en sammenligning).
5. Instruksjoner for inn-/utgang (I/O)
De muliggjør kommunikasjon mellom prosessoren og eksterne enheter. Disse instruksjonene tillater lesing og skriving av data til/fra porter (maskinvare).
- IN: Leser data fra en inngangsport.
- UTE: Sender data til en utgangsport.
6. Flyttalsinstruksjoner
Mange CPU-er har matematiske koprosessorer (eller spesielle instruksjoner) dedikert til å jobbe med desimaltall (flyttall). Disse instruksjonene tillater operasjoner som:
- Addisjon, subtraksjon, multiplikasjon og divisjon av reelle tall.
- Trigonometriske operasjoner (sinus, cosinus, tangens).
- Logaritmiske, eksponensielle og rotoperasjoner.
Disse instruksjonene er vanligvis i samsvar med IEEE 754-standarden for numerisk presisjon.
Adresseringsmoduser
En grunnleggende del av instruksjonsdesign er hvordan plasseringen av operander identifiseres. Adresseringsmoduser definerer hvordan CPU-en får tilgang til data.
1. Umiddelbar adressering
Dataene er inkludert direkte i instruksjonen. Det er raskt, men det tillater ikke å endre verdier uten å endre instruksjonen.
MOV AX, 5
2. Direkte adressering
Minneadressen som inneholder dataene er spesifisert eksplisitt.
MOV AX,
3. Indirekte adressering
Effektivadressen hentes fra innholdet i en post. Svært fleksibel og brukes til strukturer og koblede lister.
MOV AX,
4. Indeksert adressering
Adressen beregnes ved å legge til en base og en indeks (for eksempel for å traversere arrayer). Den bruker spesielle registre som SI-, DI- eller base + offset-registre.
MOV AX,
Instruksjonsformater: forskjellige typer avhengig av arkitekturen
Strukturen til en instruksjon kan variere avhengig av arkitekturen. Vanlige formater inkluderer:
4-veisformat
Den inneholder to operander, en resultatplassering og adressen til neste instruksjon. Den er nå foreldet på grunn av kompleksiteten.
3-veisformat
Den spesifiserer to operander og en destinasjonsadresse. Det er vanlig i moderne RISC-arkitekturer.
2-veisformat
Bruk en kildeoperand og en destinasjonsoperand (destinasjonen kan også bidra med verdi). Populært på x86 og andre CISC-arkitekturer.
1-veis format
Bare én operand er spesifisert; den andre antas å være akkumulatoren. Vanlig i eldre prosessorer og enkle systemer.
0-adresseformat (stabelbasert)
Operasjonene bruker stakken til å hente og lagre operander og resultater. Svært effektivt for stakkbaserte maskiner, som for eksempel noen programmerbare kalkulatorer.
Makroinstruksjoner og pseudo-opkoder
For å forbedre produktiviteten tilbyr mange assemblere makroinstruksjoner , som utvider en enkelt linje til flere faktiske instruksjoner. Disse er nyttige for å unngå å gjenta komplekse mønstre eller for å lage strukturer på høyt nivå som løkker eller betingede setninger.
den pseudo-opkoder De er instruksjoner som assembleren oversetter internt til en reell instruksjonssekvens. For eksempel, NOP (ingen operasjon) kan oversettes som XCHG AX, AX på x86 CPU.
Assembler-direktiver
Direktiver ( også kalt pseudo-operasjoner ) er ikke instruksjoner i streng forstand. De tjener til å kontrollere samlingsprosessen, definere data, kodeseksjoner, makroer, kompileringsbetingelser osv.
Vanlige eksempler inkluderer:
- .data / .kode: De angir data- eller kodedelen.
- .org: Angir adressen som samlingen skal starte fra.
- .likning: Definerer symbolske konstanter.
Brukstilfeller for assemblerspråk
Til tross for fremveksten av høynivåspråk, er assemblerspråk fortsatt nøkkelen på flere områder:
- Utvikling av innebygde systemer og mikrokontrollere.
- Programmering av drivere, bootloadere og BIOS.
- Ekstrem optimalisering i applikasjoner som videospill eller kryptografi.
- Omvendt utvikling, feilsøking og lavnivåhacking.
Videre har opplæring i assemblerspråk fortsatt en viktig plass i informatikk- og elektronikkutdanninger, ettersom det gir en dyp forståelse av hvordan en prosessor fungerer, hvordan data lagres og manipuleres, og hvordan instruksjoner utføres på binært nivå.
Å forstå alle typer monteringsinstruksjoner, deres struktur, funksjonalitet og adresseringsmoduser gir et solid grunnlag for enhver programmerer som ønsker å fordype seg i lavnivåprogrammering eller forstå hvordan høynivåspråk til slutt oversettes til maskinkode. Selv om bruken har blitt mer spesifikk, er det fortsatt et viktig verktøy i flere kritiske områder innen programvare- og systemutvikling.