Hvordan en prosessor arbeider, del 1 Læringsmål Kompilator, interpret og maskinkode CPU, registre Enkle instruksjoner: de fire regnearter Mer informasjon om temaet
Internett Lokalnett (LAN) Mitt program Programtolker (python, java,...) Operativsystemet Prosessoren (CPU-en) Logiske porter (AND, OR, XOR,...) Transistorer
Hva bør du kunne etter dagens forelesning? Jeg forventer at dere kan 1 lese enkle x64-funksjoner og forstå hva de gjør. 2 kunne skrive x64-instruksjoner som løser et enkelt regnestykke med heltall. Ukeoppgavene er gode eksempler på hva jeg forventer nå og til eksamen.
En interpret Hvordan kjøre et program Dere kan skrive programmer i et programmeringsspråk som Python. Program i Python if 2*area() > max: Python-interpret python3 Det blir tolket av en interpret. Men hvordan lager man en interpret?
En kompilator En annen måte å kjøre et program på Program i C if (a==0) a++; Andre programgrammeringsspråk som C og C++ oversetter i stedet programmet til maskinkode. Kompilator gcc Maskinkode 00101111... Maskinkode kan utføres av CPU-en i en datamaskin.
En kompilator Slik får man laget en interpret Takket være en interpret skrevet i C kan man utføre programmer skrevet i Python. Program i Python if 2*area() > max: while (*p) { Python-interpret i C Python-interpret python3 gcc
Hva er så maskinkode? Et enkelt eksempel I Python kan vi skrive funksjonen nineteen som gir verdien 19 som resultat: def nineteen(): return 19 nineteen.py print("nineteen()", "=", nineteen())
Hva er så maskinkode? Maskinkoden for funksjonen nineteen er 0x48 0xC7 0xC0 0x13 0x00 0x00 0x00 0xC3 Hvordan kan man lage slik kode? Assemblerkode Assemblerkode er huskekoder for instruksjonene, så vi skriver heller funksjonen vår slik: movq $19,%rax # Hent 19. ret (Tegnet # angir en kommentar.)
x64 Intel x64 Vår eksempel-cpu kjører x64 og er laget av Intel og AMD. Den finnes i de aller fleste personlige datamaskiner i dag.
x64 Von Neumann-maskinen CPU CPU ALU Registre inndata utdata inndata utdata Minne prosessor Minne prosessor
Registrene Registre Inne i CPUen ligger noen få spesielle variabler kalt registre. De består alle av 8 byte (64 bit). Vi skal bruke 9 av dem: Navn Bruk %RAX «Accumulator», dvs svar %RCX «Counter» %RDX «Data» %RDI «Destination index» %RSI «Source index» %R8 alt mulig %R9 alt mulig %R10 alt mulig %R11 alt mulig
Det viktigste er å flytte ting! Instruksjoner Den aller viktigste instruksjonen heter movq og den kopierer data. Den kan kopiere en fast verdi (angitt med $ foran) til et register innholdet av ett register til et annet Eksempler movq $4,%RAX # Kopier verdien 4 til register %RAX movq %RDX,%R8 # Kopier innholdet av register %RDX til %R8
Resultatet; hvor skal det? Funksjonens svar Målet med en funksjon er å beregne et svar som skal ligge i %RAX-registeret. Funksjonen nineteen Vår funksjon nineteen finner da svaret slik: movq $19,%rax # Hent 19. Retur Når svaret er klart, kan funksjonen returnere ved å bruke instruksjonen ret: ret
Navnet på funksjonen Funksjonens navn Nå kan vi gi funksjonen vår navnet sitt. Til dette trenger vi to linjer:.globl nineteen: nineteen
Den ferdige funksjonen Funksjonen nineteen komplett Da har vi den komplette filen nineteen.s: nineteen.s # def nineteen(): Hent verdien 19..globl nineteen nineteen: movq $19,%rax # Hent 19. ret (Filer med assemblerkode skal slutte med.s på samme måte som Python-filer skal slutte på.py.) I assemblerkode er alle linjer unntatt navn: rykket inn.
Vi må teste funksjonen Testing av funksjonen Til å teste funksjonen vår trenger vi et lite C-program: #include <stdio.h> extern long nineteen (); test-nineteen.c int main (void) { long res = nineteen(); printf("nineteen() = %d\n", res); } (Dere skal slippe å skrive slike C-programmer; de vil dere alltid få utlevert helt ferdig.)
Vi må teste funksjonen Kjøring av testprogrammet Testprogrammet koples sammen med funksjonen vår og kjøres etter denne oppskriften: $ gcc -o test-nineteen test-nineteen.c nineteen.s $./test-nineteen nineteen() = 19 ($-tegnet i eksemplene brukes for å angi at linjen er en kommando som brukeren gir.)
Enkel regning Noen flere instruksjoner I tillegg til instruksjonene movq Flytt en verdi ret Returner fra en funksjon har vi noen instruksjoner for regning: addq Legg til en verdi subq imulq negq Trekk fra en verdi Multipliser med en verdi Skift fortegn på en verdi
Alle skikkelige funksjoner har parametre Parametre Funksjoner kan ha parametre, dvs verdier som brukes som grunnlag for beregningen. I assemblerkode ligger parametrene i disse registrene når funksjonen vår blir kalt: %RDI %RSI %RDX 1. parameter 2. parameter 3. parameter NB! Dette gjelder for Linux. Andre systemer, som Windows, har andre regler.
Alle skikkelige funksjoner har parametre Et eksempel Vi skal lage en funksjon som dobler en verdi. I Python ville vi skrevet: def doble (v): return v + v print("doble(88)", =, doble(88)) I assemblerkode skriver vi doble.s # def doble(v): Beregn den doble verdien av v. doble:.globl doble movq %rdi,%rax # Hent v addq %rdi,%rax # og legg til v. ret
Alle skikkelige funksjoner har parametre Et testprogram kan se slik ut: #include <stdio.h> extern long doble (long v); test-doble.c int main (void) { long res = doble(17); printf("doble(17) = %d\n", res); } Resultatet av kjøringen blir $ gcc -o test-doble test-doble.c doble.s $./test-doble doble(17) = 34
Divisjon Divisjon Divisjon er litt sær, men følgende oppskrift fungerer: 1 Legg dividend (den verdien vi skal dele) i %RAX. 2 Legg divisor (den verdien vi skal dele på) i ett av registrene %R8, %R9, %R10 eller %R11. 3 Utfør de to instruksjonene cqo idivq %rn 4 Da kommer svaret i %RAX og resten fra divisjonen i %RDX.
Divisjon Et eksempel Skriv en funksjon som beregner a b c. f.s # def f(a, b, c): Beregn a * b / c f:.globl f movq %rdi,%rax # Hent a og imulq %rsi,%rax # gang med b movq %rdx,%r8 # Hent c og cqo # idivq %r8 ret # del a*b med c.
Divisjon Testprogrammet ser slik ut: #include <stdio.h> test-f.c extern long f (long a, long b, long c); int main (void) { long res = f(171, 211, 10); printf("f(171,211,10) = %d\n", res); } Resultatet av kjøringen blir $ gcc -o test-f test-f.c f.s $./test-f f(171,211,10) = 3608
For de som syntes dette var interessant Mer å lese Randal E Bryant & David R O Hallaron: Computer systems a programmer s perspective, 3rd edition. Pearson 2016. https://software.intel.com/en-us/articles/ introduction-to-x64-assembly er en kort introduksjon til x64 fra Intel. http://download.intel.com/products/processor/manual/ 325462.pdf er den fulle spesifikasjonen av x64. 4670 sider!