Maskinsprog Martin Zachariasen, DIKU Litteratur: Patterson & Hennessy, kap. 3 Programmer og ordrer Ordretyper Operander og deres placering Ordreformat Procedurekald Andre arkitekturer 1
Stored-program konceptet von Neumann maskinen: Data og programmer gemmes i arbejdslageret som en sekvens af tal. Eksempel: Memory Accounting program (machine code) Editor program (machine code) Processor C compiler (machine code) Payroll data Book text Source code in C for editor program (fig. 3.7) 2
Definitioner Ordre: Betegnelse for en kommando, som findes i en datamats maskinsprog. Ordren bestemmer éntydigt, hvilken operation og hvilke operander der benyttes. Program: Sekvens af ordrer. Maskinsprog: Den mest primitive form på hvilken man kan skrive de ordrer, en datamat skal udføre; det er den form som et udførbart program findes på i arbejdslageret. 3
Maskinsprog: oversigt Der er normalt ordrer for Aritmetik: addition, subtraktion, o.s.v. Logik: logisk and, or, xor, not, shift o.s.v. Dataoverførsel: læsning fra og skrivning til lager Hopordrer: afvig (ubetinget) fra den sekventielle udførsel af ordrer ved at hoppe til en given ordre, herunder specielt procedurekald Valg: betingede hop, dvs. udfør hop hvis en bestemt betingelse er opfyldt Afkodning: Hvordan finder maskinen ud af, hvad det er for en ordre? Vi tager udgangspunkt i MIPS arkitekturen fra 1985. 4
Addition i maskinsprog Addition: add a, b, c Alle MIPS s aritmetiske ordrer skal have tre operander, d.v.s. a = b + c + d + e må omskrives til add a, b, c add a, a, d add a, a, e # a = b+c # a = a+d = b+c+d # a = a+e = b+c+d+e Altså er tre ordrer nødvendige for at summere de fire variable. 5
Oversættelse fra C Et lille stykke C-program indeholder: a = b + c; d = a - e; Oversætteren (compileren) skal producere tilsvarende kode, f.eks. add a, b, c sub d, a, e Resultatet er nu i symbolsk maskinsprog (assembler). Ikke et brugervenligt sprog! 6
Oversættelse fra C (forts.) En lidt mere kompliceret C-ordre: f = (g + h) - (i + j); Denne C-ordre kan f.eks. oversættes til: add t0, g, h # temporær variabel t0 = g+h add t1, i, j # temporær variabel t1 = i+j sub f, t0, t1 # f = t0-t1 = (g+h)-(i+j) Oversætteren opretter to nye variable, t0 og t1, for at kunne udtrykke programmet i maskinens begrænsede tre operander pr. ordre notation. 7
Registre Operander kan lagres i registre og i arbejdslageret. MIPS har 32 registre à 32 bit (et ord). Oversætteren tildeler registre til programvariable. F.eks. i det tidligere eksempel: f = (g + h) - (i + j); kan variablerne f,g,h,i,j tildeles registrene $s0,$s1,$s2,$s3,$s4. Det oversatte program bliver f.eks. add $t0,$s1,$s2 add $t1,$s3,$s4 sub $s0,$t0,$t1 # $t0 = g+h # $t1 = i+j # $s0 = $t0-$t1, dvs. f=(g+h)-(i+j) 8
MIPS registre Nr. Navn Brug 0 $zero konstanten 0 1 $at assembler 2-3 $v0-$v1 resultater 4-7 $a0-$a3 argumenter 8-15 $t0-$t7 temporære 16-23 $s0-$s7 gemte (saved) 24-25 $t8-$t9 temporære 26-27 $k0-$k1 operativsystem 28 $gp global pegepind 29 $sp stak-pegepind 30 $fp frame-pegepind 31 $ra returadresse : bevares ved procedurekald 9
Registre og arbejdslager Simple variable kan gemmes i registre; store data- strukturer (f.eks. arrays) må placeres i arbejdslageret. Aritmetiske operationer kan kun udføres på operander lagret i registre (på RISC-maskiner). Der kræves ordrer til dataoverførsel mellem registre og arbejdslageret (data transfer instructions). Arbejdslagerets indhold tilgås via adressen (byte- eller ord-adresse). 12 8 4 0 Address 100 10 101 1 Data Processor Memory (fig. 3.3) 10
Dataoverførsel imellem registre og arbejdslager Data flyttes fra arbejdslageret til et register ved anvendelse af en hent-ordre (load). Hent-ordrens opbygning i MIPS: operationens navn: lw registret der skal hentes register der indeholder adressen i arbejdslageret hvorfra data skal hentes (base register) en konstant der angiver en forskydelse af den angivne adresse (offset) Den komplementære operation kaldes en gem-ordre (store). 11
Oversættelse med hent og gem C-tildelingssætning: A[12]=h+A[8]; Antagelser: Ordrer: h A $s2 $s3 lw $t0,32($s3) # $t0 = A[8] add $t0,$s2,$t0 # $t0 = h+a[8] sw $t0,48($s3) # A[12] = h+a[8] Bemærk at vi benytter byte-adresse forskydningen når vi udregner adresserne for A[8] og A[12]. 12
Oversættelse med variabelt array-indeks C-tildelingssætning: g=h+a[i]; Antagelser: Ordrer: g h A i $s1 $s2 $s3 $s4 add $t1,$s4,$s4 # $t1 = 2*i add $t1,$t1,$t1 # $t1 = 4*i add $t1,$t1,$s3 # $t1 = A[i] s adresse lw $t0,0($t1) # $t0 = A[i] add $s1,$s2,$t0 # g = h+a[i] 13
Indkodning af ordrer Repræsentation af MIPS-ordren add $t0, $s1, $s2 som decimaltal: 0 17 18 8 0 32 som binære tal: 000000 10001 10010 01000 00000 100000 Denne indkodning benævnes maskinkode, og placeringen af de forskellige felter kaldes ordreformatet. 14
Indkodning af en R-type ordre op rs rt rd shamt funct 6 bit 5 bit 5 bit 5 bit 5 bit 6 bit op: ordre-operation (opcode) rs: første kilde-operand rt: anden kilde-operand rd: modtager resultatet (destination) shamt: antal skift funct: funktion (vælger varianten af operationen) 15
Indkodning af en I-type ordre Ordrer som f.eks.: lw sw $t0,32($s3) $t0,48($s3) op 6 bit rs 5 bit rt 5 bit address 16 bit op: ordre-operation (opcode) rs: register der indeholder lageradressen rt: register der skal hentes/gemmes address: adresseforskydning 16
Fra C til bit-mønster C-ordre: A[300]= h + A[300]; Symbolsk maskinsprog (assembler): lw $t0,1200($t1) add $t0,$s2,$t0 sw $t0,1200($t1) Indkodning (maskinsprog): address/ op rs rt rd shamt funct 100011 01001 01000 0000 0100 1011 0000 000000 10010 01000 01000 00000 100000 101011 01001 01000 0000 0100 1011 0000 17
Betingede hop Det der adskiller en datamaskine fra en simpel regnemaskine er, at den kan træffe beslutninger. Basale ordrer: beq register1, register2, L1 Hop til ordren med label L1 hvis værdien af register1 er lig med værdien af register2. bne register1, register2, L1 Hop til ordren med label L1 hvis værdien af register1 er forskellig fra værdien af register2. Disse to ordrer kaldes for betingede hop (conditional branches). 18
If-then-else konstruktion C-ordre: if (i==j) f=g+h; else f=g-h; Antagelser: f g h i j $s0 $s1 $s2 $s3 $s4 Assembler: bne $s3,$s4,else # hop hvis i!=j add $s0,$s1,$s2 # f=g+h j Exit # hop til Exit Else: sub $s0,$s1,$s2 # f=g-h Exit: Ordren j er et ubetinget hop til en fast adresse (unconditional branch/jump) 19
While-løkke C-sætning: while (save[i]==k) i=i+j; Antagelser: Assembler: i j k save $s3 $s4 $s5 $s6 Loop: add $t1,$s3,$s3 # $t1 = 2*i add $t1,$t1,$t1 # $t1 = 4*i add $t1,$t1,$s6 # $t1 = save[i] s adresse lw $t0,0($t1) # $t0 = save[i] bne $t0,$s5,exit # hop hvis save[i]!=k add $s3,$s3,$s4 # i=i+j j Loop # hop til Loop Exit: Multiplikation af i med 4 hver gang kan undgås! 20
Sammenligning af heltal Antag vi har to variable og der er gemt i registrene $s0 og $s1. Spørgsmål: Er? Værdierne af de to registre sammenlignes ved at benyttes ordren slt (set on less than): Less:... slt $t0,$s0,$s1 # $t0=1 hvis a<b (ellers 0) bne $t0,$zero,less # hop til Less hvis $t0!=0... 21
Switch sætning Udførsel af switch kommando ved anvendelse af en hoptabel. C-program: switch (k) { case 0: f=i+j; break; case 1: f=g+h; break; case 2: f=g-h; break; case 3: f=i-j; break; } Antagelser: f g h i j k 4 JumpTable $s0 $s1 $s2 $s3 $s4 $s5 $t2 $t4 JumpTable er en array der indeholder fire adresser svarende til de fire labels som der skal hoppes til. 22
Switch-sætning (forts.) Assembler: slt $t3,$s5,$zero # test om k<0 bne $t3,$zero,exit # hvis k<0 Exit slt $t3,$s5,$t2 # test om k<4 beq $t3,$zero,exit # hvis k>=4 hop til Exit add $t1,$s5,$s5 # $t1 = 2*k add $t1,$t1,$t1 # $t1 = 4*k add $t1,$t1,$t4 # $t1 = JumpTable[k] s adr. lw $t0,0($t1) # $t0 = JumpTable[k] jr $t0 # hop efter $t0 L0: add $s0,$s3,$s4 # k=0: f=i+j j Exit # hop ud L1: add $s0,$s1,$s2 # k=1: f=g+h j Exit # hop ud L2: sub $s0,$s1,$s2 # k=2: f=g-h j Exit # hop ud L3: sub $s0,$s3,$s4 # k=3: f=i-j Exit: Ordren jr er et ubetinget hop til en adresse givet ved et register (jump register). 23
Procedure-kald og parameteroverførsel Procedure-kald Understøttes ved ordren jump-and-link jal ProcedureAdresse der gemmer adressen på den efterfølgende ordre i registret $ra før hoppet udføres. Parameteroverførsel Sker via registrene $a0-$a3 (primært) eller stakken (sekundært). Returnerede værdier Sker via registrene $v0-$v1. Stakken Stak-pegepinden $sp peger på toppen af stakken; af historiske grunde vokser stakken nedad. 24
Register-spilling og parameteroverførsel Hvis en procedure kalder en ny procedure, skal den gemme tilbagehopsadressen ($ra); derfor skal $ra gemmes i lageret (register-spilling). Regler for parameteroverførsel ved gentagne indlejrede kald: Caller save: Den kaldende procedure har ansvaret for at gemmme og genfremhente registre, der skal bevares over kaldet. Callee save: Den kaldte procedure har ansvaret for at gemmme og genfremhente registre, der skal bevares over kaldet (benyttes efterfølgende). 25
Ikke-rekursiv procedure C-procedure (ombytter element k og k+1 i array v): swap(int v[], int k) { int temp; temp = v[k]; v[k] = v[k+1]; v[k+1] = temp; } Assembler: swap: add $t1, $a1, $a1 # $t1 = k * 2 add $t1, $t1, $t1 # $t1 = k * 4 add $t1, $a0, $t1 # $t1 = v[k] s adresse lw $t0, 0($t1) # $t0 (temp) = v[k] lw $t2, 4($t1) # $t2 = v[k+1] sw $t2, 0($t1) # v[k] = $t2 (=v[k+1]) sw $t0, 4($t1) # v[k+1] = $t0 (temp) jr $ra Benytter slet ikke stakken (temporære variable gemmes i registre). 26
Procedure-kald: Generel anvendelse af stak Stakken anvendes til: 1. Parametre (hvis der er mere end fire) 2. Retur-adresse (hvis andre procedurer kaldes) 3. Gemte registre (hvis disse ændres) 4. Lokale variable (hvis der ikke er plads i registrene) High address $fp $fp $sp $fp Saved argument registers (if any) $sp Saved return address Saved saved registers (if any) Local arrays and structures (if any) $sp Low address a. b. c. (fig. 3.12) 27
Rekursiv procedure C-procedure: int fact (int n) { if (n<1) return (1); else return (n*fact(n-1)); } Assembler: fact: subi $sp,$sp,8 # plads til 2 paa stak sw $ra, 4($sp) # gem returadressen sw $a0, 0($sp) # gem argumentet n slti $t0,$a0,1 # test om n<1 beq $t0,$zero,l1 # hvis n>=1 hop til L1 addi $v0,$zero,1 # returner 1 addi $sp,$sp,8 # pop 2 fra stak jr $ra # hop retur L1: subi $a0,$a0,1 # argument=n-1 jal fact # kald fact med n-1 lw $a0,0($sp) # retabler argument n lw $ra,4($sp) # retabler returadresse addi $sp,$sp,8 # juster stak-pegepind mul $v0,$a0,$v0 # returner n*fact(n-1) jr $ra # hop retur 28
Et større eksempel: Sortering af heltal Vi vil benytte følgende C-kode, der sorterer n heltal i en array v: sort (int v[], int n) { int i, j; for (i = 1; i < n; i++) { for (j = i-1; j >= 0 && v[j] > v[j+1]; j--) { swap(v,j); } } } (lettere modificeret udgave af fig. 3.25) 29
Sortering af heltal (forts.) Assembler (start og slut af procedure): sort: addi $sp, $sp, -20 # plads til 5 reg paa stak sw $ra, 16($sp) # gem $ra sw $s3, 12($sp) # gem $s3 sw $s2, 8($sp) # gem $s2 sw $s1, 4($sp) # gem $s1 sw $s0, 0($sp) # gem $s0... exit1: lw $s0, 0($sp) # genetabler $s0 lw $s1, 4($sp) # genetabler $s1 lw $s2, 8($sp) # genetabler $s2 lw $s3, 12($sp) # genetabler $s3 lw $ra, 16($sp) # genetabler $ra addi $sp, $sp, 20 # genetabler stak-pegepind jr $ra # afslut procedure 30
Sortering af heltal (forts.) Assembler (procedurekrop):... move $s2, $a0 # kopier parameter $a0 (gem) move $s3, $a1 # kopier parameter $a1 (gem) addi $s0, $zero, 1 # i = 1 for1tst: slt $t0, $s0, $s3 # $t0 = 0 hvis i >= n beq $t0, $zero, exit1 # hop ud hvis i >= n addi $s1, $s0, -1 # j = i - 1 for2tst: slti $t0, $s1, 0 # $t0 = 1 hvis j < 0 bne $t0, $zero, exit2 # hop ud hvis j < 0 add $t1, $s1, $s1 # $t1 = j * 2 add $t1, $t1, $t1 # $t1 = j * 4 add $t2, $s2, $t1 # $t2 = v[j] s adresse lw $t3, 0($t2) # $t3 = v[j] lw $t4, 4($t2) # $t4 = v[j+1] slt $t0, $t4, $t3 # $t0 = 0 hvis v[j+1]>=v[j] beq $t0, $zero, exit2 # hop ud hvis v[j+1]>=v[j] move $a0, $s2 # 1. parameter til swap (v) move $a1, $s1 # 2. parameter til swap (j) jal swap # kald swap addi $s1, $s1, -1 # j = j - 1 j for2tst # hop tilbage exit2: addi $s0, $s0, 1 # i = i + 1 j for1tst # hop tilbage... 31
1000 0000 hex Text Anvendelse af arbejdslager Arbejdslageret benyttes til: 1. Stakken $sp 7fff ffff hex Stack 2. Dynamiske data 3. Statiske data 4. Programmet 5. Operativsystemet Dynamic data $gp 1000 8000 hex Static data pc 0040 0000 hex 0 Reserved (fig. 3.22) 32
Adressering: De fem muligheder i MIPS 1. Immediate addressing op rs rt Immediate 2. Register addressing op rs rt rd... funct Registers Register 3. Base addressing op rs rt Address Memory Register + Byte Halfword Word 4. PC-relative addressing op rs rt Address Memory PC + Word 5. Pseudodirect addressing op Address Memory PC Word (fig. 3.17) 33
Andre arkitekturer Kronologisk oversigt over populære maskiner og deres overordnede arkitektur: Maskine Antal Arkitektur År registre EDSAC 1 accumulator 1949 IBM 701 1 accumulator 1953 CDC 6600 8 load-store 1963 IBM 360 16 register-memory 1964 Intel 8008 1 accumulator 1972 DEC VAX 16 register-memory, mem-mem 1977 Intel 8086 1 extended accumulator 1978 Motorola 68000 16 register-memory 1980 Intel 80386 8 register-memory 1985 MIPS 32 load-store 1985 HP PA-RISC 32 load-store 1986 SPARC 32 load-store 1987 PowerPC 32 load-store 1992 DEC Alpha 32 load-store 1992 Intel Itanium 128 load-store 2001 34
OPGAVE 1 Følgende program skal udføres: Loop: lw $t3, 0($t1) beq $t1, $t2, Exit addi $t1, $t1, 4 bne $t3, $zero, Loop Exit: Registre og lager har dette indhold: $t1 = 1000 $t2 = 1012 $t3 = 0 Memory[1000] = 2 Memory[1004] = 0 Memory[1008] = 7 Memory[1012] = 2 Hvad er værdien af register $t1 da programmet når til Exit? 1. 1004 2. 1008 3. 1012 4. 0 35