Så här fungerar datorer Baserad på T-J Hallbergs minimalmaskin. 2008-08-26 Högskolan i Jönköping/JTH Ragnar Nohre



Relevanta dokument
Elektroteknik MF1016 föreläsning 9 MF1017 föreläsning 7 Mikrodatorteknik

Det finns en hemsida. Adressen är

Föreläsningsanteckningar 2. Mikroprogrammering I

HF0010. Introduktionskurs i datateknik 1,5 hp

F5 Introduktion till digitalteknik

Grunderna i stegkodsprogrammering

Minnet. Minne. Minns Man Minnet? Aktivera Kursens mål: LV3 Fo7. RAM-minnen: ROM PROM FLASH RWM. Primärminnen Sekundärminne Blockminne. Ext 15.

Föreläsning 3.1: Datastrukturer, en översikt

LV6 LV7. Aktivera Kursens mål:

Laboration Kombinatoriska kretsar

Digitalteknik EIT020. Lecture 15: Design av digitala kretsar

Per Holm Lågnivåprogrammering 2014/15 24 / 177. int och double = = 2, 147, 483, 647

F2: Motorola Arkitektur. Assembler vs. Maskinkod Exekvering av instruktioner i Instruktionsformat MOVE instruktionen

Övningsuppgifterna i kapitel F avser FLIS-processorn, vars instruktioner och motsvarande koder definieras i INSTRUKTIONSLISTA FÖR FLISP.

T1-modulen Lektionerna Radioamatörkurs OH6AG OH6AG. Bearbetning och översättning: Thomas Anderssén, OH6NT Heikki Lahtivirta, OH2LH

DIGITALTEKNIK. Laboration D173. Grundläggande digital logik

Övning1 Datorteknik, HH vt12 - Talsystem, logik, minne, instruktioner, assembler

Grundläggande digitalteknik

Föreläsningsanteckningar 3. Mikroprogrammering II

Moment 2 - Digital elektronik. Föreläsning 1 Binära tal och logiska grindar

Grundläggande datavetenskap, 4p

0.1. INTRODUKTION Instruktionens opcode decodas till en språknivå som är förstålig för ALUn.

ALU:n ska anslutas hur då?

System S. Datorarkitektur - en inledning. Organisation av datorsystem: olika abstraktionsnivåer. den mest abstrakta synen på systemet

F5 Introduktion till digitalteknik

Laboration Kombinatoriska kretsar

Ext-13 (Ver ) Exempel på RTN-beskrivning av FLEX-instruktioner

Datorsystemteknik DAV A14 Föreläsning 1

Försättsblad till skriftlig tentamen vid Linköpings Universitet

Kommentarmaterial, Skolverket 1997

Datorsystem Laboration 2: Minnesmappade bussar

Ext-13 (Ver ) Exempel på RTN-beskrivning av FLEX-instruktioner

c a OP b Digitalteknik och Datorarkitektur 5hp ALU Design Principle 1 - Simplicity favors regularity add $15, $8, $11

Exempeluppgift i Logikstyrning. 1 Inledning. 2 Insignaler och utsignaler

Tenta i Digitalteknik

Lågnivåprogrammering. Föreläsning 2 Lågnivåprogrammering. Binära tal. En enkel modell av datorns inre

D/A- och A/D-omvandlarmodul MOD687-31

Digital- och datorteknik

Multiplikation genom århundraden

ANDRA BASER ÄN TIO EXTRAMATERIAL TILL. Matematikens grunder. för lärare. Anders Månsson

EDA215 Digital- och datorteknik för Z

Föreläsning 2. Operativsystem och programmering

Datorteknik. Den digitala automaten. En dator måste kunna räkna! Register och bussanslutning

F2 Datarepresentation talbaser, dataformat och teckenkodning EDAA05 Datorer i system! Roger Henriksson!

Högskolan i Halmstad Digital- och Mikrodatorteknik 7.5p. Lista på registeruppsättningen i PIC16F877A Datablad TTL-kretsar 74-serien

Digital elektronik CL0090

Programmerbar logik. Kapitel 4

Digitalteknik och Datorarkitektur

SVAR TILL TENTAMEN I DATORSYSTEM, VT2013

Bonusmaterial till Lära och undervisa matematik från förskoleklass till åk 6. Ledning för att lösa problemen i Övningar för kapitel 5, sid

Digital- och datorteknik

Tentamen Datorteknik D del 2, TSEA49

1 Aylas bil har gått kilometer. Hur långt har den (2) gått när hon har kört en kilometer till?

Laboration Sekvenskretsar

Lokala kursplaner i Matematik Fårösunds skolområde reviderad 2005 Lokala mål Arbetssätt Underlag för bedömning

Provmoment: Ladokkod: Tentamen ges för: Tentamen TE111B El3. Namn: Personnummer: Tentamensdatum: Tid: 14:00-18:00.

Södervångskolans mål i matematik

Design av digitala kretsar

7) Beskriv tre sätt att överföra parametrar mellan huvudprogram och subrutin.

IE1205 Digital Design: F6 : Digital aritmetik 2

VHDL och laborationer i digitalteknik

Att använda pekare i. C-kod

DE FYRA RÄKNESÄTTEN (SID. 11) MA1C: AVRUNDNING

Digital Aritmetik Unsigned Integers Signed Integers"

Digital- och datorteknik

Tentamen i IE1204/5 Digital Design onsdagen den 5/

A-del motsvarande KS1

Laboration i digitalteknik Introduktion till digitalteknik

Decimaltal Kapitel 1 Decimaltal Borggården Diagnos Rustkammaren Tornet Sammanfattning Utmaningen Arbetsblad Läxboken 1:1 Läxa 1 1:2 1:3 Läxa 2 1:4

Kompletterande lösningsförslag och ledningar, Matematik 3000 kurs A, kapitel 6

Förberedelser: Sätt upp konerna i stigande ordningsföljd (första inlärningen) eller i blandad ordningsföljd (för de elever som kommit längre).

DIGITALTEKNIK I. Laboration DE2. Sekvensnät och sekvenskretsar

DIGITALA TAL OCH BOOLESK ALGEBRA

Datorsystem. Övningshäfte. Senast uppdaterad: 22 oktober 2012 Version 1.0d

Tenta i Digitalteknik

Repetitionsuppgifter i Matematik inför Basår. Matematiska institutionen Linköpings universitet 2014

CE_O3. Nios II. Inför lab nios2time

Tentamen i Digitalteknik, EITF65

Talsystem Teori. Vad är talsystem? Av Johan Johansson

Att göra investeringskalkyler med hjälp av

LABORATIONSINSTRUKTION

Övning1 Datorteknik, HH vt12 - Talsystem, logik, minne, instruktioner, assembler

Digital- och datorteknik

Digital- och datorteknik

F2 Binära tal EDA070 Datorer och datoranvändning

IE1204/IE1205 Digital Design

Tentamen i Digitala system - EITA15 15hp varav denna tentamen 4,5hp

Laboration D184. ELEKTRONIK Digitalteknik. Sekvensnät beskrivna med VHDL och realiserade med PLD

Tentamen i IE1204/5 Digital Design onsdagen den 5/

Föreläsning 6: Introduktion av listor

2-5 Decimaltal Namn: Inledning. Vad är ett decimaltal, och varför skall jag arbeta med dem?

Digitala Projekt (EITF11)

Struktur: Elektroteknik A. Digitalteknik 3p, vt 01. F1: Introduktion. Motivation och målsättning för kurserna i digital elektronik

TENTAMEN Datorteknik (DO2005) D1/E1/Mek1/Ö1

IT för personligt arbete F5

LABORATION DATORTEKNIK Y,C,I DATORTEKNIK D

Tentamen i Digital Design

Laboration nr 3 behandlar

Datormodell. Datorns uppgifter -Utföra program (instruktioner) Göra beräkningar på data Flytta data Interagera med omvärlden

Stack och subrutiner Programmeringskonventionen

Transkript:

Baserad på T-J Hallbergs minimalmaskin 2008-08-26 Högskolan i Jönköping/JTH Ragnar Nohre

Innehåll 1 Översikt... 3 2 Binära tal och koder... 3 2.1 Positionssystemet... 3 2.2 De binära talen... 4 2.3 Kilo Mega Giga... 5 2.4 Hexadecimala tal... 5 2.5 Negativa tal... 5 2.6 Decimaltal... 6 2.7 Övningar... 7 3 Modelldatorn... 8 3.1 De vitala delarna... 8 3.2 Instruktionsuppsättningen... 9 3.3 Programmering... 10 3.4 Övningar... 11 4 Digitalteknik... 12 4.1 Asynkrona kretsar... 12 4.2 Synkrona kretsar... 16 5 Datorns styrenhet och mikroprogrammet... 19 6 Datorns stack och subrutinanrop... 22 1.1. Implementering av modelldatorns stack... 23 7 Simulatorn... 24 7.1 Inledande experiment... 24 7.2 Kör programmet... 24 7.3 Stega igenom programmet... 25 8 Laboration... 25 9 Referenser... 25 2

Så här fungerar datorer Datorn uppfanns på 1940 talet. Maskinen är fullkomligt genial, men ändå förvånansvärt enkel. Det går faktiskt att förstå hur den fungerar och med några enkla logiska kretsar kan man också bygga en liten primitiv dator, som tack vare sin programmerbarhet kan simulera/efterlikna varje annan typ av maskin. Bland annat kommer den att kunna efterlikna en godtyckligt avancerad dator (det är bara ett mycket långt program som fattas ). På sent 70-tal byggde datorkonstruktör Tord-Jöran Hallberg en enkel dator som han kallade minimalmaskinen. Syftet var att lära blivande (civil)ingenjörer hur datorer fungerar. Tyvärr finns Hallbergs pedagogiska bok [Hal79] inte längre i tryck, men i den här skriften skall vi i alla fall studera en liten dator som nästan är en kopia av Hallbergs konstruktion. Vi bifogar också en windowsapplikation som simulerar den lilla datorn. 1 Översikt Först skall vi titta på binära tal. Detta är viktigt för det går till exempel inte att förstå hur datorns adressbuss fungerar om man inte först förstått principen bakom binära tal. Därefter skall vi lära oss att programmera en mycket enkel dator. Vi programmerar i assemblerkod och översätter sedan till s.k. maskinkod bestående 1:or och 0:or. Då vi väl har förstått hur man programmerar datorn är det dags att undersöka dess innanmäte. Det är nu vi kommer att lära oss hur datorn fungerar! Vi börjar med snabb introduktion till digitaltekniken och tittar på grundläggande digitala komponenter såsom logiska grindar, register, minnen och bussar. Det är med dessa beståndsdelar man bygger datorer. Därefter kommer vi att koppla i hop beståndsdelarna till den primitiva lilla dator som klarar av att exekvera vår maskinkod. 2 Binära tal och koder För att förstå hur en dator fungerar måste man förstå principen bakom binära heltal. Vi ska här också se hur man kan representera negativa tal med den så kallade tvåkomplementmetoden och decimaltal med mantissa och exponent. Vi startar mjukt och inleder med det så kallade positionssystemet. 2.1 Positionssystemet För ca 2000 år sedan skrev man i Europa tal med romerska siffror. Man angav ett tal genom att rada upp symboler för ental, femtal, tiotal, femtiotal, osv., på ungefär samma sätt som man kan bygga upp en summa pengar genom att rada upp mynt och sedlar av olika valörer. Detta system är opraktiskt om man vill ange mycket stora tal eftersom det krävs att man känner till många olika symboler (många olika sedelvalörer). Systemet är också opraktiskt för den som vill utföra matematiska operationer såsom multiplikation och division. Idag anger vi istället tal med hjälp av det så kallade positionssystemet. Så vitt man vet har detta utmärkta system upptäckts av tre olika kulturer (av indier, araber och mayaindianer). 3

Eftersom alla läsare redan känner till positionssystemet tar vi oss friheten att beskriva det ganska slarvigt: Betrakta exempelvis talet 7023. Siffran 3 står i entalsposition och bidrar därför med värdet 3 till den totala summan. Siffran 2 som står i tiotalsposition bidrar med termen 20, emedan 7:an bidrar med 7000 eftersom den står i tusentalspositionen. Lägg märke till att nollan har en viktig platsfyllande funktion även om den inte bidrar till summan. Generellt sett kan vi med positionssystemet beskriva godtyckligt stora tal med hjälp av en sekvens av siffror, där varje siffras bidrag till den totala summan beror på dess position i sekvensen. För oss som gillar matematiska formler kan vi säga att det fyrsiffriga talet d d d skall tolkas som nedanstående summa: 3 2 1d 0 3 3d2d1d0 d k k= 0 d 10 k Hitintills har vi använt basen tio. Det betyder att vi använt tio olika siffersymboler (0,1,2..9) och att värdet mellan två närliggande positioner skiljer sig med en faktor tio (ental, tiotal, hundratal, osv). För den som gärna räknar på fingrarna är det naturligt att använda basen tio. Mayaindianerna kunde ha basen 20, eftersom de alltid gick i sandaler. För en dator är basen två mest praktisk, även om man i datorns barndom också experimenterade med basen tre. 2.2 De binära talen För att förstå hur en dator fungerar är det viktigt att man förstår sig på de binära talen, alltså hur man med positionssystemet kan beskriva tal med basen 2. Vi tar oss fortfarande friheten att beskriva detta relativt slarvigt. Den som tycker att det är svårt bör fråga sin lärare, kamrat, mattebok, Google, eller någon annan tillförlitlig källa (se även [Whi06 s.45]). Ett binärt tal skrivs som en sekvens av ettor och nollor. Varje siffra kallas för en bit (från binary digit). Exempel på ett binärt tal är: 10111 Från höger till vänster kallas siffrorna entalssiffra, tvåtalssiffra, fyrtalssiffra, åttatalssiffra, osv. Vi använder alltså två olika siffror (0 och 1), och värdet mellan två närliggande positioner skiljer sig en faktor 2. I ovanstående tal är en- två- fyr- och sextontalssiffrorna 1 emedan åttatalssiffran är 0. Då man väl insett detta är det lätt att omvandla ovanstående tal till decimal form: 1x16 + 0x8 + 1x4 + 1x2 + 1x1 = 23 Den matematiska formeln ser ungefär ut som förut. Det fyrsiffriga talet tolkas som: 3 3d2d1d0 d k k= 0 d 2 k d 3 d 2 d 1 d 0 skall 4

2.3 Kilo Mega Giga Med hjälp av n stycken bitar kan man representera 2 n olika tal. Exempel: med 8 bitar (en byte) kan man representera 256 olika tal och med tio 1024. En datalog måste lära sig de tio första tvåpotenserna utantill (1,2,4,8, 1024). Eftersom 1024 är ungefär lika med ett tusen brukar dataloger kalla talet 1024 för ett Kilo och förkorta detta med K. Med hjälp av 20 bitar kan man representera 2 upphöjt till 20 tal, dvs 2 10 x 2 10 = 1024x1024. Det är ungefär detsamma som 1000x1000, alltså en miljon, och dataloger kallar därför detta tal för en Mega och förkortar det med M. Med hjälp av 30 bitar kan man representera 1024x1024x1024 olika tal, dvs ungefär tusen miljoner eller en miljard. Resultatet kallas en Giga, förkortning G. 2.4 Hexadecimala tal Det är lätt att det blir fel om man försöker skriva av ett längre binärtal. På datorskärmar och i skrift brukar man därför använda det hexadecimala systemet. Det innebär att man har 16 olika symboler: 0,1,2,...9,A,B,C,D,E,F, där symbolen A har värdet tio, B elva, osv, upp till F som har värdet femton. Så här översätter man ett binärt tal till ett hexadecimalt: Dela in det binära talets bitar i grupper om fyra bitar (starta från höger) och tolka sedan varje sådan grupp som ett heltal mellan 0 och 15. Exempel: Talet 10110011010011 skriver vi först som 10 1100 1101 0011 och sedan som 2CD3 (alternativt 2cd3). Ibland kan det vara lite oklart vilken bas som används. Hur skall man tex. tolka talet 10? Pratar man binärt så betyder det två, decimalt betyder det tio och hexadecimalt sexton. Om det finns risk för missförstånd bör man indikera basen med ett litet suffix (b,d eller h): Exempel: 10h = 16d = 10000b. 2.5 Negativa tal Vi skall här beskriva hur man kan representera negativa tal med hjälp av den så kallade tvåkomplementmetoden. För att vi skall får en ökad förståelse av denna metod tittar vi först på dess decimala motsvarighet, tiokomplementmetoden. 2.5.1 Tiokomplementmetoden Antag att vi har ett decimalt mekaniskt räkneverk som kan visa ett visst antal siffror med hjälp av lika många hjul. Låt oss anta att räkneverket har 4 hjul och alltså kan visa talen 0000, 0001, 0002, 9999. Låt oss vidare anta att verket från början är inställt på talet 0003 och att vi nu vrider det baklänges 5 steg. Tre minus fem är minus två men vi hamnar på talet 9998 (0002, 0001,0000,9999,9998). Det är därför lämpligt att representera talet -2 (minus två) som 9998. Antag exempelvis att vi vill addera talet 5 till talet -2. Vi ställer in räkneverket på 9998 (minus två), stegar fram 5 steg och hamnar på 0003, som sig bör. 5

Hur skriver man då exempelvis talet -35 med hjälp av denna metod? Vi tänker oss att vi ställer in räkneverket på 0000 och sedan backar 35 steg, på vilket tal kommer vi då att hamna? Det vore omständligt att behöva räkna baklänges, låt oss istället dela upp processen i två delmoment: Först backar vi ett steg, och hamnar på talet 9999, och sedan backar vi de 34 resterande stegen och hamnar på 9999 minus 34 dvs. på 9965. Generellt sett så representerar vi talet x som: 9999 1 9999 1 Det är enkelt att utföra beräkningen i huvudet eftersom man aldrig behöver låna då man subtraherar x från 9999. I talet 0035, byt varje siffra d mot sitt komplement dvs. mot siffran 9-d, 0 blir 9, 3 blir 6 och 5 blir 4, 0035 blir alltså 9964. Addera sen 1, och få 9965. 2.5.2 Tvåkomplementmetoden Antag att en dator representerar tal med 8 bitar. Hur skall man representera talet -x? Vi gör som förut. Vi ställer in räkneverket på 00 0 och backar först ett steg till 111 1 och sedan de resterande (x- 1) stegen. Talet x representeras alltså som: 11111111 1 11111111 1 Att subtrahera x från 11111111 är superenkelt eftersom vi inte behöver låna. Faktum är att vi bara behöver invertera alla bitar i x. Vi har nu kommit fram till tvåkomplimentmetoden: För att hitta den binära representationen av talet x: Invertera alla bitar i x och addera sedan 1 till resultatet. Exempel: Talet 35 skrivs 00010011 binärt. För att få -35 inverterar vi först alla bitar och erhåller 11101100, därefter vi adderar 1 och får 11101101. Antag att vi i stället vill göra tvärt om. Vi har ett negativt tal som vi vill tolka, exempelvis talet 11101101 ovan. Vi skulle kunna köra ovanstående negationsprocedur baklänges men vi kan lika gärna utnyttja det faktum att två negationer tar ut varandra och köra negationsproceduren framlänges en gång till: Invertera 11101101, resultat 00010010, addera 1, resultat 00010011 = 35. Med hjälp av tvåkomplementmetoden och 8 bitar kan man representera alla heltal mellan -128 och +127, där -128 alltså skrivs 10000000. Generellt sett har den inledande (mest signifikanta) biten värdet 1 om talet är negativt. Denna bit kallas därför ibland teckenbit (trots att det inte är så enkelt att den bara representerar ett minustecken). 2.6 Decimaltal Som bekant tillåter oss det förträffliga positionssystemet att uttrycka icke heltaliga tal med hjälp av ett decimalkomma (ex 314,152). Värdet mellan två närliggande positioner skiljer sig fortfarande med en faktor 10. Till höger om decimalkommat är alltså positionerna värda en tiondel, en hundradel, en tusendel, osv. Den matematiska formeln för hur man skall tolka ett decimaltal ser ungefär ut som den formel vi gav förut: 3 3d2d1d0, d 1d 2d 3 d k k= 3 d 10 k 6

Binärt har vi motsvarande notation. Exempel på ett icke heltaligt binärtal är 1011,101. Till höger om (binär)kommat är positionerna värda en halv, en fjärdedel, en åttondel, osv. Som bekant brukar man ibland skriva decimaltal med vetenskaplig notation. Exempelvis kan 0,0013 skrivas som 1,3 x 10-3 och 314,15 som 3,1415 x 10 2. Vi kan göra likadant binärt. Exempelvis kan vi skriva talet 1011,101 som 1,011101 x 2 3. Precis som i det decimalla fallet anger exponenten (dvs. 3:an) hur många steg åt höger som kommatecknet skall flyttas. En normal dator brukar vanligtvis använda 32 bitar för att lagra ett decimaltal. Av dessa brukar 8 bitar användas till att lagra exponenten i tvåkomplementform. Exponenten måste alltså vara ett heltal mellan -128 och +127. Av de resterande 24 bitarna används en bit som teckenbit, och resterande 23 bitar till att lagra den så kallade mantissan. 2.7 Övningar Här följer några övningsuppgifter (möjliga tentamensuppgifter): 1. Omvandla följande binära tal till decimaltal: a. 00000001 b. 00000010 c. 00000100 d. 00000101 e. 00110110 2. Omvandla följande decimaltal tal till 8-bitars binära tal: a. 4 b. 8 c. 16 d. 36 e. 100 3. Omvandla följande hexadecimala tal till decimaltal: a. 01 b. 0A c. A2 d. FF 4. Omvandla följande tal till decimaltal under förutsättning att tvåkomplementmetoden används för att representera negativa tal a. 11111111b b. 10000000b c. 11001001b d. A2h e. FFh 5. Ett decimaltal lagras med 23 bitars mantissa, dvs med 23 bitars noggrannhet. Hur många decimala siffrors noggrannhet motsvarar detta? 7

3 Modelldatorn I detta avsnitt skall vi först redogöra för modelldatorns fem vitala delar och därefter för hur man programmerar den. 3.1 De vitala delarna Då man pratar om en dators arkitektur brukar man mena de saker som en programmerare måste känna till för att kunna programmera datorn med assemblerkod. Vår dator består av fem vitala delar: ett minne, ett programräknarregister (PR), ett ackumulatorregister (AR) ett in- och ett utregister (se figuren) 3.1.1 Minnet Idag är det inte ovanligt att en PC har ett RAM-minne som är 2GB stort. Vår modelldator har ett mycket litet minne. Endast 256 st. 12-bitars ord. Man kan tänka sig minnet som en tabell med 256 rader där varje rad rymmer 12 bitar. Raderna är numrerade från 0 till 255. Minnet innehåller datorns program men också en dataarea som programmet kan Figur 1 Modelldatorns arkitektur läsa och skriva till. Det är upp till programmeraren att avgöra vilka delar av minnet som skall användas för program respektive data. Programmet består av instruktioner som kommer att utföras en och en i den ordning som de står i minnet. (Idén att lagra ett program i ett minne kallas stored program concept, och den brukar tillskrivas von Neuman [Whi06 s.76].) 3.1.2 Programräknaren Datorn innehåller en så kallad programräknare (direktöversättning från engelskans program counter, men ett bättre namn vore egentligen instruktionspekare). I vårt fall är detta ett 8 bitars heltal som lagras i ett litet minnesregister (PR). Heltalet pekar på en rad i minnet, nämligen på den rad (eller adress) som innehåller den instruktion som datorn står på tur att exekvera. Ett program i vår dator kan vara upp till 256 instruktioner långt, och det är därför som vår programräknare måste bestå av 8 bitar (i de äldre pentiumprocessorerna var programräknaren 32 bitar lång och i de nya 64). 3.1.3 In- och ut- registren En normal dator kommunicerar med den yttre världen. Det kan vara via ett tangentbord, mus, temperaturgivare, bildskärm, värmeelement, eller andra IO-enheter. Vår enkla dator kommunicerar via ett inregister och ett utregister. Exakt hur dessa register är kopplade till den yttre världen bryr vi oss inte om. Inregistret innehåller alltid ett 12 bitars tal som kommer från yttervärden och via utregistret kan datorn skicka ut ett annat 12-bitars tal. 3.1.4 Ackumulatorn Slutligen måste programmeraren känna till ackumulatorregistret (AR). Som vi snart skall se lagrar ackumulatorn alltid resultatet av den senaste beräkningen, vi återkommer snart till detta register. 8

3.2 Instruktionsuppsättningen Vi har tidigare sagt att ett datorprogram är en sekvens av instruktioner som lagras i datorns minne. Låt oss nu titta på dessa instruktioner (vi har lånat hela instruktionsuppsättningen från Hallbergs minimalmaskin [Hal79]). Nedanstående tabell visar de 10 operationerna. OP ASSEMBLER KOD BETYDELSE VERKAN 0000 LOAD adr Läs AR m[adr] 0001 STORE adr Skriv m[adr] AR 0010 ADD adr Addera AR AR + m[adr] 0011 SUB adr Subtrahera AR AR m[adr] 0100 JUMP adr Hopp PR adr 0101 PJUMP adr Hopp om AR 0 If (AR 0) PR adr 0110 IN Läs från IN AR IN 0111 OUT Skriv till UT OUT AR 1000 CALL adr Tillfälligt hopp 1001 RETURN Återhopp från call Figur 2 Modelldatorns instruktionsuppsättning I ovanstående tabell avser adr en minnesadress, dvs. ett tal mellan 0 och 255 som pekar ut en rad i minnet. I kolumnen verkan har vi gett en kortfattad beskrivning av vad instruktionen gör. Här betecknar m[adr] det 12-bitar ord som ligger lagrat på minnesplatsen adr. Vidare skall den bakåtriktade pilen utläsas tilldelas. Det register som står till vänster om pilen kommer att fyllas med det värde som står till höger. Nedan förklarar vi instruktionerna lite mer noggrant. 3.2.1 LOAD och STORE Instruktionen LOAD adr innebär att det ord som ligger lagrad på den angivna adressen skall kopieras in till ackumulatorregistret. Om exempelvis talet 23 ligger lagrat på plats 5 i minnet så kommer LOAD 5 att ladda ackumulatorn med talet 23. Instruktionen STORE gör tvärt om. Om exempelvis ackumulatorn innehåller talet 23 så kommer STORE 8 att skriva in talet 23 på adress 8 i minnet. 3.2.2 ADD och SUB Instruktionen ADD adr innebär att det tal som ligger på den angivna minnesplatsen skall adderas till det tal som redan ligger i ackumulatorn. Om exempelvis talet 23 ligger lagrat på adress 5 och talet 7 redan finns i ackumulatorn så kommer ADD 5 att göra så att ackumulatorn får värdet 30. Instruktionen SUB adr subtraherar istället talet. I ovanstående exempel skulle SUB 5 göra så att ackumulatorn fick värdet 7-23, dvs -16. 3.2.3 IN och OUT Instruktionen IN gör så att ackumulatorn fylls med det värde som ligger i in-registret och OUT kopierar ackumulatorns värde till utregistret. 9

3.2.4 JUMP och PJUMP Normalt kommer datorn att exekvera instruktionerna en och en i den ordning som de står skrivna i minnet. Efter det att datorn har utfört en instruktion kommer alltså programräknaren (PR) att stega fram ett steg. Det finns dock två undantag, nämligen vid instruktionerna JUMP och PJUMP. Låt säga att adress 200 innehåller instruktionen JUMP 150. Detta betyder att programmet skall hoppa tillbaka till adress 150. Efter det att instruktionen utförts kommer med andra ord PR att ha fått värdet 150. PJUMP (positiv JUMP) är så kallat villkorligt hopp. Om det tal som ligger lagrat i AR är större eller lika med noll så skall man hoppa, men i annat fall så skall exekveringen fortsätta utan hopp. Låt säga att adress 200 innehåller instruktionen PJUMP 150 och att ackumulatorn innehåller talet 4. PR kommer då att få värdet 150. Men om AR istället hade innehållit talet -2 skulle exekveringen ha fortsatt till nästa adress (201). 3.2.5 CALL och RETURN Instruktionerna CALL och RETURN används vid så kallade subrutinsanrop. Vi återkommer till dessa lite längre fram i denna skrift. 3.3 Programmering Vi skall nu studera ett litet exempel på ett datorprogram (hämtat från [Hal79]). Datorn används här för temperaturövervakning. Vi antar att vi har en temperaturmätare kopplad till datorns inregister (som alltså kommer att innehålla aktuell temperatur mätt i grader Celsius) och att vi har en varningslampa kopplad till bit 0 i utregistret. Vi vill att lampan skall lysa om temperaturen är större än 30 grader. Programmet fungerar såsom beskrivs av flödesschemat: Först skall datorn ladda AR med den aktuella temperaturen och därefter subtrahera talet 30 från AR. Om AR:s värde nu är positivt skall den ladda AR med en etta som den sedan skickar till utgången (tänd lampa) men om värdet är negativt skall den istället skicka en nolla till utgången (släck lampa). Då lampan har tänts eller släckts skall programräknaren hoppa tillbaka till programmets början och på nytt läsa in temperaturen till ackumulatorregistret. Programmets kod syns här nedanför. Läsaren bör först övertyga sig om att han eller hon verkligen förstått flödesschemat, och därefter om att assemblerkoden överensstämmer med schemat! Nedan har vi också översatt assemblerkoden till binär maskinkod. Denna översättning är rättfram. För varje instruktion skriver vi dess 4 bitars operationskod (se tidigare figur) 10

följt av adressparametern som ett binärt tal. Om instruktionen inte har någon adressparameter skriver vi istället 8 nollor efter operationskoden. Adress maskinkod assemblerkod Kommentar 0 0110 00000000 IN Läs in temperaturen till AR 1 0011 00001011 SUB 11 Subtrahera talet 30 (m[11]=30) 2 0101 00000110 PJUMP 6 Hoppa om temp 30 3 0000 00001001 LOAD 9 Kopiera m[9] = 0 till AR 4 0111 00000000 OUT A till OUT (släck) 5 0100 00000000 JUMP 0 Repetera loopen 6 0000 00001010 LOAD 10 Kopiera m[10] = 1 till A 7 0111 00000000 OUT A till OUT (tänd) 8 0100 00000000 JUMP 0 Repetera Loopen 9 0000 00000000 0 Konstant (för att släcka) 10 0000 00000001 1 Konstant (för att tända) 11 0000 00011110 30 Konstanten 30 grader Figur 3 Temperaturprogrammet. En etta skickas till ut-registret om temperaturen är större än 30 grader. Många läsare tycker säkert att programmet är en smula omständligt. Exempel: För att kunna skicka ut en etta på utgången måste vi först ladda in den till ackumulatorn, och för att kunna göra detta måste vi först se till så att konstanten 1 ligger på någon minnesadress. Det hade varit lättare att programmera datorn om det hade funnits en instruktion som kunde skicka ut en etta direkt på utgången, eller i alla fall en instruktion som direkt kan ladda in en 1:a till ackumulatorn, men det finns inga sådana instruktioner. Den lilla datorn har en instruktionsuppsättning som är tillräckligt kraftfull för att vi skall kunna skriva alla typer av program, men den innehåller inga instruktioner som kan undvaras. Priset vi betalar för en minimal instruktionsuppsättning är att programmen blir längre och långsammare än vad de hade blivit om datorn hade haft fler instruktioner. 3.4 Övningar och LAB Nedanstående uppgifter skall redovisas under laboration 1. 1. Vad kommer vidstående program att skicka ut på utgången om talet på ingången är: a. 75 b. 100 c. 125 2. Översätt programmet till binär maskinkod 3. Provkör programmet i simulatorn och verifiera att det fungerar så som du tror. 4. Skriv ett program som låter en varningslampa (kopplad till utregistret) lysa om en kylskåpstemperatur (talet på inregistret) är mindre än 2 eller större än 8 grader. a. Rita ett flödesschema för programmet. (Obs, hitta ej på egna symboler utan använd samma symboler som vi använder i denna skrift.) b. Översätt flödesschemat till assemblerkod c. Översätt assemblerkoden till maskinkod d. Provkör programmet i simulatorn 11

4 Digitalteknik Vi har nu bekantat oss med datorn och lärt oss att programmera den. Men hur ser datorn ut inuti om man lyfter på locket? I detta kapitel skall vi titta på datorns hårdvara. Med hjälp av elektronik kan man bygga så kallade logiska grindar och andra digitala kretsar. Vi skall studera detta spörsmål här utan att tränga in alltför djupt. För att förstå en dator fungerar behöver man nämligen bara kunna lite grann digitalteknik. (En fördjupad kunskap ges ju dessutom i en annan kurs.) 4.1 Asynkrona kretsar Vi skiljer mellan asynkrona och synkrona kretsar. Här skall vi titta på de asynkrona, de kallas så får att de inte har någon klockpuls som ingång. 4.1.1 inverteraren Inverteraren är en extremt enkel logisk grind. Stoppar man in en etta kommer det ut en nolla, och vice versa. Figuren visar hur man ritar en inverterare med europeisk notation. Det finns även en amerikansk notation (som används i kursboken [Whi06] ). Inverteraren kallas ibland för en icke-krets (eng. NOT), eftersom utgången är 1 om ingången icke är 1. Den så kallade sanningstabellen visar sambandet mellan in och utgång. Att den kallas sanningstabell är för övrigt ett kvarhäng från logiken där man pratar om sant och falskt istället för 1 och 0. 4.1.2 AND-grinden AND-grinden (och) är en annan enkel logisk grind. Grinden har 2 eller flera ingångar och en utgång. Utgången får värdet 1 om alla ingångar har värdet 1 (första ingången och andra och tredje osv), annars får utgången värdet 0. Figuren visar den europeiska notationen för en ANDgrind med två ingångar. I sanningstabellen har utgången värdet 1 om alla ingångar är 1. 4.1.3 OR-grinden OR-grinden (eller) är en annan grundläggande grind med en utgång och 2 eller flera ingångar. Utgången får värdet 1 12

om minst en av ingångarna är 1 (första ingången eller andra eller tredje osv). I sanningstabellen är utgången 1 om någon ingång är 1. 4.1.4 Switch Nedanstående figur visar en liten tillämpning på AND- och OR- grindar, nämligen en swich. För att se hur kretsen fungerar, betrakta de tre AND-grindarna på vänster sida. Om insignalen a=0 så kommer deras utsignaler att vara 0, men om istället a=1 så släpper de igenom de tre insignalerna x 1,x 2 och x 3. Motsvarande sak gäller för insignal b och de högra AND-grindarna. Om vi sätter a=1 och b=0 så släpper kretsen igenom de vänstra insignalerna till y 1,y 2 och y 3, men om istället a=0 och b=1 så bestäms utgångarna av insignalerna från höger. Vi har med andra ord byggt en slags omkopplare eller switch. Figur 4 En switch, och hur vi vanligtvis ritar den med förenklad buss-notation. I den högra delen av ovanstående figur visar vi samma switch med en förenklad bussnotation. En buss är ett antal parallella bit-ledningar som vi i våra figurer ritar som en tjock pil. I ovanstående figur får bussen (y) antingen sitt data från den vänstra (x) eller högra (x ) in-bussen, beroende på vilken styrsignal (a eller b) som är 1. 4.1.5 Andra grindar Om man sätter en inverterare på utgången av en OR-gind får man en NOR-grind (Not OR). Grindens symbols syns i figuren. Istället för att rita ut hela inverteraren på OR-grindens 13

utgång har man ersatt den av en cirkel. På motsvarande sätt kan man konstruera en NANDgrind (Not AND). Veriefera själv att NOR och NAND grindarnas sanningstabeller stämmer med vad man skulle ha fått om man kopplade på en inverterare på utgången av en OR resp. AND-grind! Man kan även rita inverterare på vissa ingångar, men de resulterande grindarna får oftast inte något speciellt namn. 4.1.6 XOR En XOR-grind (exklusive or) har utsignalen 1 om en och endast en av insignalerna är 1. Figuren visar hur man ritar ex XOR-grind. Figuren visar också att man kan bygga en XOR-grind med hjälp av AND- OR- och NOT- grindar. Läsaren bör övertyga sig om att den nedre konstruktionen verkligen fungerar som en XOR-grind. 4.1.7 Styrd invertering Här intill ser vi en liten tillämpning av XOR-grindar. Antag att det ligger en 0:a på den insignal som heter inv. Då kommer utgångarna till höger att ha samma värden som ingångarna från vänster (verifiera detta). Om å andra sidan inv=1 så kommer utgångarna att ha motsatta värden. Kretsen kommer med andra ord att invertera insignalerna om inv=1. Figuren visar också en förenklad notation där vi ersatt de fyra inkommande respektive utgående ledningarna med två tjocka pilar (bussar). En inbuss och en utbuss. 4.1.8 Adderare Nedanstående figur visar hur två binära tal har adderats manuellt med papper och penna. Det är mycket enkelt. Man börjar med entalssiffran och fortsätter åt vänster. Varje steg i denna additionsprocess involverar tre in-bitar (en eventuell minnessiffra från föregående steg och en bit från vardera talet) och två ut-bitar (resultatbit och minnessiffra). Figuren visar också hur man åstadkommer additionen med digitalteknik genom att kaskadkoppla 14

ett antal enkla adderarkretsar med tre ingångar och två utgångar. Till höger i figuren syns sanningstabellen för en sådan enkel adderarkrets (full-adder) (se även kursboken [Whi06, s59]). Vår vana trogen har vi också kryddat figuren med en figur som visar adderaren med förenklad bussnotation. På de två inbussarna ligger två heltal, och på utbussen deras summa. Figur 5 En adderare uppbyggd av kaskadkopplade fulladders. 4.1.9 Aritmetisk Logisk Enhet En ALU (arithmetic logic unit) är en krets som kan utföra några enkla matematiska/logiska operationer på två tal, exempelvis addera talen. I vår lilla dator har ALU:n två indatabussar och en utdatabuss. Varje buss består av 12 bitar. På indatabussarna ligger de två talen och beräkningsresultatet hamnar på utdatabussen. Vår ALU har dessutom två styringångar, add och sub. Om man lägger en 1:a på add och en nolla på sub så kommer ALU:n att addera de två talen, om man i stället lägger 1:an på sub så kommer den att subtrahera det ena talet från det andra (se figur). Figuren visar också hur ALU:n kan tänkas se ut inuti, uppbyggd av komponenter vi redan känner till. Om vi lägger en 1:a på sub så kommer kretsen dels att invertera alla bitar på den vänstra inbussen och dessutom att addera ytterligare en 1:a till den totala summan. Läsaren bör känna igen detta som det första respektive andra steget i tvåkomplementmetoden. 15

Figur 6 En aritmetisk logisk enhet som kan addera och subtrahera 4.2 Synkrona kretsar Synkrona kretsar kännetecknas av att de har en så kallad klock-ingång. I en digital konstruktion brukar alla synkrona kretsars klockingångar vara sammankopplade och matas med en gemensam klocksignal, som, styrd av en kvartskristall, oscillerar mellan 0 och 1. Utgångarna (och de inre tillstånden) i en synkron krets kan bara ändra sig då klockpulsen går från 0 till 1. Eftersom alla kretsar matas med en gemensam klocksignal kommer de att ändra sina utsignaler samtidigt, dvs. synkront. 4.2.1 D-Vippan Genom att koppla ihop ett antal logiska grindar i en återkopplad krets (dvs. en krets där vissa utgångar leds tillbaka till vissa ingångar) kan man bygga en så kallad D-vippa. Vi bryr oss inte om att förklara hur kopplingen ser ut utan fokuserar istället på D-vippans funktion. Vippan är ett slags en-bits minne, den har nämligen ett inre tillstånd som kan vara antingen 0 eller 1. Vippan har en utsignal som anger det inre tillståndet, och två insignaler. Den ena insignalen kallas clock och den andra kallas D (som i data). Varje gång clock-signalen ändras från 0 till 1 (dvs på positiv flank) så läser vippan av sin D-ingång, och minns den. Se tidsdiagrammet i nedanstående figur. (Givet insignalerna clock och D, bör du själv kunna rita utsignalen). Med hjälp av n st D-vippor kan man bygga ett n-bitars register. Figuren här intill visar hur vi vår simulator åskådliggör ett sådant register. Vid varje klockpulsögonblick läser registret av styrsignalen a, och om den är 16

1 så kommer registret att minnas (registrera) de bitar som vid klockpulsögonblicket låg på inbussen. På utbussen finns alltid de bitar som registret minns. 4.2.2 T-Vippan T-vippan påminner om D-vippan, men istället för en D-ingång har den en ingång som kallas T (som i toggle=invertera). Varje gång clock-signalen ändras från 0 till 1 läser vippan sin T- ingång, och om den är 1 så inverteras (togglas) det aktuella tillståndet. Tidsdiagrammet i nedanstående figur illustrerar detta. (Givet insignalerna clock och T, bör du själv kunna rita utsignalen). 4.2.3 Räknaren I nedanstående figur har vi sammankopplat flera T-vippor. Vi har fått ett slags minnesregister som rymmer 4 bitar. Vid varje klockpuls kommer vissa av bitarna att togglas, vilka? Jo, AND-grindarna är kopplade på ett sådant sätt att en given T-vippa kommer att togglas om samtliga bitar till höger om den var 1 vid klockpulsögonblicket. Om exempelvis det aktuella tillståndet var 1011 så kommer det att ändras till 1100 då klocksignalen går från 0 till 1. Om man funderar en stund så inser man snart att kretsen är en binärräknare som stegar fram ett steg vid varje klockpuls. (I vår lilla modelldator kommer bland annat vår programräknare att utgöras av en sådan räknare. Vid varje klockpuls kommer den att stega fram ett steg och peka ut nästa instruktion i programmet.) 4.2.4 Registret Vi har redan sett ett register bestående av D-vippor. Vi har också sett hur man kan konstruera en synkron räknare, som stegar fram ett binärt tal vid varje klockpuls. På motsvarande sätt kan man konstruera en baklängesräknare. Figuren här intill illustrerar ett register som har alla dessa funktioner. Registret har tre styrsignaler men vid varje givet ögonblick får högst en av dem får vara aktiv. Om styrsignal a är 1 så kommer registret (vid nästa klockpuls) att registrera de bitar som ligger på inbussen. Om styrsignalen märkt +1 är aktiv så kommer det binära tal som ligger lagrat i registret att stega fram ett steg, och om -1 är aktiv så stegas talet istället bakåt ett steg. 17

4.2.5 Minneskretsar Det finns minneskretsar av olika storlekar. Ett modernt minne kan ofta lagra flera hundra MB (mega byte). I vår modelldator har vi dock ett mycket litet minne som endast kan lagra 256 st 12-bitars ord. Vi tänker oss minnet som en tabell med 256 rader, där det på varje rad står skrivet 12 bitar. Minneskretsen har flera in- och utgångar. Som ingångar har vi bland annat en adressbuss bestående av 8 st adressledningar. De nollor och ettor som ligger på adressbussen kan tolkas som ett tal mellan 0 och 255 som anger en viss rad (eller adress) i minnet. Ibland vill man läsa data från minnet och ibland vill man istället skriva data till minnet. Minnet har därför två styrsignaler, läs och skriv. Dessutom går det till minnet två databussar. En in-buss och en ut-buss, båda bussarna innehåller tolv dataledningar. Om den styrsignal som kallas läs har värdet ett så kan man på utdatabussen läsa det 12-bitars ord som ligger på den rad som adressbussen anger. Läsoperationen är asynkron, man behöver inte vänta på någon klockpuls. Om man istället vill skriva till minnet så lägger man en etta på styrsignalen skriv. Vid nästa klockpuls kommer då inbussens databitar att kopieras till den minnesadress som adressbussen anger. 18

5 Datorns styrenhet och mikroprogrammet Nedanstående figur visar hur vår lilla dator ser ut under skalet. Vi har exempelvis sett att instruktionen ADD 130 innebär att datorn skall addera innehållet på adress 130 till ackumulatorn, men hur gör datorn då den utför denna instruktion? Det är nu dags att studera datorns innanmäte! Figur 7 Vår modelldators innanmäte (lånad från [Hal79]) Komponenterna i vår dator kan påverkas av 25 styrsignaler som indikeras med siffror innanför cirklar i schemat i Fel! Hittar inte referenskälla.. Låt oss först beskriva styrsignalerna 1 till 16 (följ med i Fel! Hittar inte referenskälla.). 1. Styrsignalerna 1, 2 (och 20) avgör vilken adress som läggs ut på minnets adressbuss. Högst en av dessa styrsignaler får vara aktiv. Om styrsignal 1 är aktiv så kommer adressen från IR:s adressdel. 2. Om styrsignal 2 är aktiv så kommer ovanstående adress istället från PR. 3. Om styrsignal 3 är aktiv så kommer programräknaren att stega fram ett steg vid nästa klockpuls. 4. Styrsignalerna 4 och 5 går tillsammans med AR:s tecken-bit in i en liten logisk krets. Om utsignalen från denna krets är 1 så kommer adressen från IR att kopieras in till PR vid nästa klockpuls (innehållet i våra register påverkas bara vid klockpulser). 5. se ovan. 6. Signalerna 6 och 7 går in till vår ALU, högst en av dem får vara aktiv. Om styrbit 6 är aktiv så kommer ALU:n att addera de två inkommande tolvbitarstalen. Summan hamnar nästan omedelbart på ALU:ns utgång (vi behöver inte vänta på någon klockpuls). 19

7. Om styrbit 7 är aktiv så kommer ALU:n istället att subtrahera de två talen (det högra minus det vänstra). 8. Högst en av styrbitarna 8 och 9 får vara aktiv, om 8:an är aktiv läser man från minnet. På minnets utdatabuss hamnar då det 12-bitars ord som adressbussen pekar på. (Läsning sker asynkront, vi behöver inte vänta på någon klockpuls.) 9. Om istället styrbit 9 är aktiv kommer det 12-bitars ord som ligger på databussen att skrivas in till den utpekade adressen i minnet vid nästa klockpuls. 10. Högst en av styrbitarna 10 och 13 får vara aktiv. Styrbit 10 gör så att resultatet av ALU:ns beräkning kopieras in till AR vid nästa klockpuls. (De är det resultat som fanns på fanns på ALU:ns utgång strax före klockpulsögonblicket som kopieras till ackumulatorn. Efter klockpulsen kommer ALU:n att matas med ett nytt indata från AR och således producera ett nytt beräkningsresultat.) 11. Styrbit 11 gör så att det värde som ligger på databussen kopieras till OUT-registret (vid nästa klockpuls). 12. Högst en av styrbitarna 12, 14 och 15 får vara aktiv, styrbit 12 gör så att det man läser från minnet läggs ut på databussen. 13. Styrbit 13 gör så att databussens värde att kopieras till AR (vid nästa klockpuls) 14. Om styrbit 14 är aktiv så kommer AR:s värde att läggas ut på databussen. 15. Om styrbit 15 är aktiv så kommer IN-registrets värde att läggas på databussen. 16. Styrbit 16 medför att det värde som ligger på databussen att kopieras in till IR. Det är nu dags att skärskåda datorns funktion. Låt oss först ge en lite översiktlig beskrivning av vad datorn måste göra då den exekverar en instruktion som tex ADD 130 (häng med i Fel! Hittar inte referenskälla.): Den av PR utpekade instruktionen (ADD 130) skall via databussen kopieras in till instruktionsregistret (IR). PR skall ökas med ett. IR:s adressdel (som nu innehåller talet 130) skall sen adressera minnet så att innehållet i motsvarande minnesadress läggs ut på databussen, ALUn skall addera detta tal med det tal som låg i AR, och summan skall kopieras in till AR. Allt detta kan inte ske samtidigt. Datorn måste därför generera en sekvens av klockpulser och låta ett eller flera register påverkas vid varje klockpuls. Mellan klockpulserna måste datorn aktivera vissa styrbitar, så att de önskade händelserna äger rum. Hur åstadkommer då datorn detta? Lösningen är enkel men genial, och då man väl förstått den har man också förstått hur en dator fungerar! Datorn har ett så kallat mikrominne, det är ett förprogrammerat ROM (Read Only Memory) som lagrar ett s.k. mikroprogram. Här är alla ord (mikroinstruktioner) 25 bitar breda, och bitarna leds direkt ut till styrsignalerna. Tabellen i Fel! Hittar inte referenskälla. visar mikrominnets innehåll (varje kryss i tabellen indikerar en etta). Låt oss följa exekveringen av en instruktion (ADD 130). Det är viktigt att läsaren följer med i principschemat (Fel! Hittar inte referenskälla.). Från början har mikroprogramräknaren (µpr) värdet 0, vilket betyder att styrsignalerna bestäms av den mikroinstruktion som ligger på adress 0 i mikrominnet. Med andra ord aktiveras styrsignalerna 2,8,12 och 16. Läsaren bör övertyga sig om att detta leder till att den instruktion (i huvudminnet) som PR pekar på kommer att kopieras in till instruktionsregistret (IR) vid nästa klockpuls. Dessutom är styrsignal 18 aktiv, vilket innebär att µpr också stegar fram ett steg (vid nästa klockpuls). 20

Efter den första klockpulsen kommer således instruktionen ADD 130 att ligga i IR, och µpr att vara 1. Enligt mikroprogrammet aktiveras nu styrsignalerna 3 och 17. Styrsignal 3 gör så att PR stegar fram ett steg (vid nästa klockpuls), och 17 gör så att µpr kommer att laddas med den mikroadress som kommer från enhet K i figuren. Vad gör då denna enhet? Som vi sett tidigare innehåller varje instruktion en fyra bitars operationskod. Enhet K är ett litet ROMminne som översätter operationskoden till en adress i mikroprogrammet. Enligt tabellen i Fel! Hittar inte referenskälla. startar ADD-instruktionens mikrokod på adress 4, enhet K kommer därför att översätta ADD instruktionens operationskod (0010) till mikroadressen 4, och efter nästa klockpuls får alltså µpr detta värde. Efter den andra klockpulsen ligger alltså den aktuella instruktionen (ADD 130) fortfarande i IR och µpr har hoppat till adress 4. Här aktiveras styrsignalerna 1, 8, 12, 6 och 10. Läsaren bör övertyga sig om att innehållet på adress 130 nu läggs ut på databussen, att ALU:n adderar värdet på databussen med värdet från AR, och att summan kommer att lagras i AR vid nästa klockpuls. Även styrsignal 18 är aktiv, som resultat kommer µpr att stega fram ett steg. Efter den tredje klockpulsen ligger additionens summa i AR och µpr pekar på adress 5. Här aktiveras styrsignal 19. Vid nästa klockpuls kommer µpr därför att nollställas. Efter den fjärde klockpulsen har hela ADD 130 instruktionen utförts. PR pekar på nästa instruktion och µpr är återigen 0. Vi kan konstatera att ADD-instruktionen tog 4 klockpulser i anspråk. Detta skulle motsvara 4 nanosekunder om klockfrekvensen vore 1 GHz. Generellt sett kan man dela upp exekveringen av en instruktion i två faser. I vår lilla modelldator tar fas 1 (fetch fasen) alltid två klockpulser i anspråk. Under denna fas hämtas instruktionen från huvudminnet till IR och därefter hoppar µpr till den del av mikroprogrammet som skall utföra den aktuella instruktionen. Under fas 2 (execute) utförs den instruktionsspecifika mikrokoden. Längden av fas två beror av den aktuella instruktionen. Vår implementering av ADD-instruktionen tog två klockpulser i anspråk (men det skulle gå att korta ned den till en klockpuls såsom vi gjort med de andra instruktionerna). Adress 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 kommentar 0 X X X X X hämtfas 1 X X 2 X X X X X LOAD 3 X X X X STORE 4 X X X X X X ADD 5 X 6 X X X X X X SUB 7 X X JUMP 8 X X PJUMP 9 X X X IN 21

10 X X X OUT 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 Figur 8 Datorns mikrominne Läsaren bör nu på egen hand studera de andra operationerna i ovanstående mikroprogram. Det kan finnas tryckfel, upptäck dem i så fall! 6 Datorns stack och subrutinanrop För att det skall bli någorlunda enkelt att programmera en dator måste den ha instruktioner som möjliggör så kallade subrutinanrop. En subrutin är en kodsnutt som programmeraren vill köra från många olika ställen i programmet. T.ex. en multiplikationsalgoritm eller en algoritm som beräknar sinus för en given vinkel, etc. (Ett sätt vore att kopiera in den aktuella kodsnutten till alla ställen i programmet där den skall köras, men det resulterande programmet skulle bli ofantligt mycket större än nödvändigt och mycket svårt att underhålla och uppdatera.) Som programmerare placerar man in subrutinen på någon ledig plats i minnet. På de ställen i programmet där man vill att subrutinen skall köras ger man sedan instruktionen CALL adr, där adr är subrutinens startadress. Programräknaren kommer då att hoppa till rutinens startadress och fortsätta exekveringen där. Subrutinen måste avslutas med instruktionen RETURN, som gör så att programräknaren att hoppar tillbaka till anropspunkten. För att det hela skall fungera måste alltså CALL-instruktionen ha lagrat anropspunktens adress (PR:s aktuella värde) på något lämpligt ställe i datorns minne. Det har visat sig att en så kallad stack är en idealisk datastruktur för detta ändamål. En stack är en datastruktur som påminner om en trave tallrikar. Man kan göra tre operationer på en sådan trave: 1) Titta på den översta tallriken (operation top). 2) Placera en ny tallrik överst på stacken (op. push). 3) Ta bort den översta tallriken från stacken (op. pop). Nedanstående figur illustrerar ett relativt komplicerat programflöde som gör flera subrutinanrop. Huvudprogrammet består av en loop som startar på adress A och som gör två subrutinanrop, först till adress D och sedan till adress E. Subrutinen som startar på adress E anropar i sin tur den på adress D. Vi har alltså ett exempel på en subrutin som anropar en annan subrutin! Figuren visar också hur stacken ser ut vid olika tidpunkter. Vid varje subrutinanrop lagrar man (push) återhoppsadressen på stacken, och vid varje return skall man hoppa tillbaka till den adress som ligger överst på stacken och samtidigt avlägsna (pop) återhoppsadressen från stacken. 22

Ovanstående figur är också facit till en typisk tentamensuppgift. Läsaren bör därför övertyga sig om att han/hon förstått figuren och kan redogöra för hur stacken används vid subrutinanrop! Överkursinformation: För den som redan kan programmera i ett högnivåspråk (C, C++, Pascal, BASIC, etc) kan det vara intressant att känna till att datorn vid funktionsanrop även lagrar så kallade lokala variabler och anropsparametrar på stacken. 1.1. Implementering av modelldatorns stack I vår modelldator kommer stacken att ligga längst ned i minnesarean. Om stacken bara innehåller ett element så kommer det alltså att ligga på minnets sista adress, dvs på adress 255, och om stacken innehåller två element så kommer det översta att ligga på adress 254 och det nedersta på 255. Datorn innehåller ett så kallat stackpekarregister (SP) som alltid pekar på adressen strax ovanför stacken. Om stacken innehåller tre element kommer SP att ha värdet 252, och om stacken är tom så är SP 255. Då man pushar ett element (dvs en återhoppsadress) på stacken så skall det lagras på den adress som SP anger och därefter skall SP minskas med 1. Då man poppar ett element från stacken så skall SP ökas med 1. Hur ser då mikroprogrammet för instruktionen CALL ut? Som vi sett tidigare inleds alla våra mikroprogram av en hämtfas som laddar in instruktionen till IR och ökar PR med 1. Därefter kommer den instruktionsspecifika delen av mikroprogrammet: Den skall pusha PR:s aktuella värde (detta är återhoppsadressen, eftersom PR redan pekar på nästa instruktion) på stacken. Med andra ord skall den lagra PR på den adress som anges av SP och sedan minska SP med 1. Därefter skall PR laddas med CALL instruktionens adress (som ligger i IR). 23

Vid RETURN så skall SP ökas med 1, och den återhoppsadress som SP därefter pekar på skall sedan kopieras till PR. Mikrokoden för CALL respektive RETURN får bli en laboration! 7 Simulatorn Simulatorn är ett nyskrivet program (September 2006) som säkert innehåller många buggar (programmeringsfel), den som tror sig ha hittat ett fel bör meddela detta till mig (Ragnar). Den senaste versionen av programmet kan hämtas från http://hem.hj.se/~nora/mm/. Placera programfilen (eller en genväg till den) i den katalog varifrån du önskar köra programmet. Programmet kommer att förvänta sig att hitta två textfiler (minne.txt och microminne.txt) i den aktuella katalogen, även dessa kan hämtas från hemsidan. Starta nu programmet med ett dubbelklick. 7.1 Inledande experiment Nedanstående instruktioner bör göra så att man snabbt blir bekant med simulatorn: 1. De små cirklarna under inregistret representerar registrets minst signifikanta byte. Klicka på dem och ställ in talet 21 (hex). 2. Klicka på styrsignal 15 och observera att talet från inregistret nu hamnar på databussen. 3. Aktivera styrsignal 6. ALU:n skall nu addera talet på databussen med det tal (förmodligen 0) som ligger i AR. Summan skall synas på ALU:ns utgång. 4. Aktivera styrsignal 10 (som får AR att läsa ALU:ns värde). AR kommer inte att ändras (ännu). 5. Eftersom AR är en synkron komponent kommer den att vänta tills nästa klockpuls innan den uppdaterar sitt värde. På verktygsmenyn finns en knapp som symboliserar en ensam klockpuls, tryck på den! Observera att AR nu uppdateras med sitt nya värde (förmodligen 21). Observera också att ALU:ns utgång ändras (varför?). 7.2 Kör programmet Programmet minne.txt innehåller (från början) temperaturprogrammet. Titta på programmet i notepad, och provkör det sedan med hjälp av nedanstående instruktioner: 1. På verktygsfältet finns det en knapp som symboliserar styrenheten. Tryck in den, och observera att de styrsignaler som anges av mikroprogrammets första rad kommer att aktiveras. 2. På verktygsfältet finns det en knapp som symboliserar ett pulståg. Tryck in knappen, nu körs programmet (även om det går ganska långsamt)! 3. Fungerar programmet? Ställ in en temperatur som är mindre än 30 grader. Utregistret skall bli 0. Ställ in en hög temperatur och utregistret skall få det värde som anges i programmet. Eftersom det dröjer flera sekunder för programmet att köra en loop måste man ha lite tålamod. 24

7.3 Stega igenom programmet Avaktivera pulståget så att simulatorn stannar och generera i fortsättningen klockpulserna manuellt genom att trycka på den ensamma klockpulsknappen. Singelstega dig igenom flera flera instruktioner tills du är säker på att du förstår allt som händer i datorn! 8 Laboration Laborationen består av två uppgifter: 1. Tidigare bör du ha skrivit ett program som låter en varningslampa (kopplad till outregistret) lysa om temperaturen (från in-registret) är mindre än 2 grader eller större än 8 grader. Staga dig nu igenom detta program och verifiera att du förstår hur datorn arbetar. Redovisning: Visa programmet (minne.txt) 2. Implementera instruktionerna CALL och RETURN i mikrokod. Skriv sedan en subrutin som ökar på innehållet på adress 10 med 1 (genom att först läsa in det gamla värdet till AR, sedan addera 1, och slutligen skriva tillbaka resultatet till adress 10). Skriv sedan ett testprogram som anropar subrutinen i en oändlig loop och verifiera att innehållet på adress 10 räknas upp. Redovisning: Visa mikrokoden (microminne.txt) och testprogrammet (minne.txt) 9 Referenser [Hal79] Hur datorer fungerar. Tord-Jöran Hallberg 1979, ISBN 91-44-16591-9 [Whi06] How Computers Work. Ron White 2006, ISBN 0-7897-3424-9 [Noh06] mm1a.exe, simulatorn från http://hem.hj.se/~nora/mm/ 25