Maskinkode

Maskinkode er det "sprog" som en computer, eller mere præcist: computerens CPU, forstår. Et computerprogram, der skal afvikles på en computer, skal optræde som maskinkode, afvikles af maskinkode eller omdannes til maskinkode. 

Dette "sprog" er dybest set en tabel, som knytter en lille, simpel "handling" til forskellige binære tal. Et program i maskinkode består af en række instruktioner i form af binære tal i en bestemt rækkefølge, som CPU'en læser ét for et, og udfører den handling der er knyttet til hvert af dem.

Tabellen over tal og instruktioner kaldes for instruktionssættet for den pågældende CPU. Forskellige typer CPU'er har forskellige instruktioner; samme handling (f.eks. at lægge to tal sammen) vil som ofte være knyttet til forskellige binære tal hos forskellige CPU'er, og én CPU kan have instruktioner i sit instruktionssæt, som ikke findes hos en anden slags CPU. 

Ud over den binære værdi tildeles hver instruktion en opkode, der er et symbolsk navn for instruktionen til brug for mennesker. Et eksempel på en opkode kunne være MOV, der flytter data mellem to steder i maskinen. Den samme opkode kan dække over flere binære instruktioner, f.eks. flytning mellem to steder i lageret, flytning mellem to registre og flytning mellem register og lager. Den binære kode kan bestå i et antal bit plus bit, der angiver operanderne for instruktionen, f.eks. en adresse, et register eller en litterale (konstant). Opkoderne er næsten altid baseret på en form for engelsk.

Maskinarkitektur
Oprindeligt blev et program skrevet til en bestemt computer. Skulle programmet afvikles på en anden computer, skulle det enten skrives forfra eller oversættes på ny til den anden maskine. Man begyndte derfor at konstruere computere med en fælles arkitektur, dvs. de samme registre og det samme instruktionssæt. Et program udviklet til én maskine kan da uden videre afvikles på en anden maskine, der er større eller mindre, hvis de deler den samme arkitektur. Et eksempel på sådan en fælles arkitektur er IBMs System/360, der spændte over mange meget forskellige modeller. Arkitekturen blev fortsat i System/370 og op til IBMs mainframes i dag. Også UNIVAC udviklede tidligt en fælles arkitektur for firmaets maskiner.

CISC og RISC
Der findes grundlæggende to måder, som en CPU kan behandle sine instruktioner på. I den ene, i en såkaldt CISC, Complex Instruction Set Computer, afvikler CPU'en et eget program, et mikroprogram, der læser en instruktion, aktiverer de forskellige kredsløb i CPU'en afhængigt af instruktionen og indholdet i forskellige registre (der ikke altid er synlige for programmører) og læser den næste instruktion. Denne metode tillader, at den samme arkitektur kan implementeres på vidt forskellige hardware, idet kostbar elektronik på billigere modeller kan simuleres af mikroprogrammet. En instruktion kan være meget kraftfuld og gøre mange ting på én gang. Til gengæld kan metoden være forholdsvis langsommelig.

I den anden, RISC, Reduced Instruction Set Computer, findes intet mikroprogram. Alle operationer udføres direkte af dertil beregnede kredsløb i CPU'en. Det går meget hurtigt, men kræver mere hardware. De fleste instruktioner kan kun gøre én, simpel ting. Programmøren skal altså til tider anvende flere, svage instruktioner for at udføre en opgave. Da de fleste programmer i dag skrives i et højniveausprog, belaster dette ikke programmøren. De finere detaljer med at udnytte maskinen bedst muligt, håndteres af oversætteren.

Generering af maskininstruktioner

Håndassemblering
Simplest foretager programmøren en såkaldt håndassemblering af sit program. Programmet skrives med brug af opkoder, også kaldet mnemokoder. Programmøren slår disse op i en manual og angiver i stedet de binære koder, en for en, samt de operander, også på binær form, der er nødvendige. Også udregning af adresser foretages af programmøren. Det færdige program kan lægges ind i computeren på flere måder. Tidligere kunne dette f.eks. ske ved brug af et antal kontakter med angivelse af adresse og indhold på en celle i lageret.

Assemblering
For at lette dette arbejde udvikledes den symbolske assembler. Det er et lille program, der selv besørger opslaget af mnemokoder, udregning af adresser, generering af de binære koder og evt. ekspandering af macroer.

Oversættelse
I de såkaldte højniveausprog ser programmøren sjældent ret meget til de enkelte maskininstruktioner. I stedet håndteres mere abstrakte begreber som datastrukturer, løkker/iterationer, beslutninger m.fl. Disse omdannes da af en compiler til maskininstruktioner. Disse skal ofte behandles af en linker, der kan sammenbinde flere uafhængigt oversatte moduler og korrigere adresser.

Fortolkning
Et program behøver ikke oversættes til maskinkode. I stedet kan instruktionerne i højniveausproget fortolkes af en fortolker, en for en umiddelbart før de skal eksekveres. Forskellige rutiner i fortolkeren udføres alt efter, hvad der er behov for. Disse rutiner er i maskinkode.

Virtuelle maskiner
En anden måde at lade et oversat program afvikle på forskellige maskiner, selv om de ikke deler arkitektur, er at anvende en virtuel maskine. Oversætteren danner da instruktioner til denne virtuelle maskine i stedet for de rigtige maskininstruktioner. Der skal så skrives en fortolker af denne virtuelle kode til hver arkitektur, som skal kunne afvikle programmerne. Et tidligt eksempel er byte-code, også kendt som p-kode. Et nyere eksempel er den kode, der afvikles af Java Virtual Machine, JVM. Selv om dette system er skabt til Java, kan programmer, skrevet i visse andre sprog, også afvikles af JVM. 

Kodninger
Datalogi