2. Att skriva och exekvera ett enkelt program i MISSE

2.1 Färdig program-mall i MISSE

När du startar MISSE så ser du att det redan finns färdig källkod i editorn. Detta fungerar som en mall för den nya programmeraren. I DatorTeknik -kursen utgår man alltid från denna mall :

/*
 * New file
 */

#include <iregdef.h>

	.data # address at 0x10000000

# --- insert variables here

	.text # address at 0x00400000
	.globl main
main:

# --- insert code here

	jr $31
	nop

Nedan en kort förklaring på vad dessa rader betyder :
  • /*
  • Påbörjar en kommentering, precis som i Java och C.
  • */
  • Avslutar en kommentering.
  • #
  • Anger att resten av raden är en kommentar. Följande rad kommer inte att tolkas som en kommentar.
  • #include <iregdef.h>
  • Hämtar in en fil som kan innehålla både källkod och deklarationer.
    iregdef.h är en fil som ger bl.a. möjligheten att använda namn för register, dvs. zero istället för $0.
    iregdef.h är dessutom en fil som MISSE hanterar internt, denna fil behöver inte existera som en riktig fil på ditt hemområde.
  • .data
  • Alla variabler som deklareras under .data kommer att hamna i Data-segmentet.
    .data kan även ta emot ett argument, ett hexadecimalt tal, som anger adressen fr.o.m. vilken variablerna kommer att lagras.
    Ifall inga argument anges kommer denna adress att vara 0x10000000, eller första lediga adress inom Data-segmentet.
  • .text
  • All programkod skall alltid hamna innanför Text-segmentet (med undantag för speciella operativsystems-rutiner som hamnar i .ktext).
    Precis som .data så godkänner även .text att man anger en adress som argument. Lämnar man bort denna kommer instruktionerna att skrivas fr.o.m. adress 0x00400000.
  • main:
  • Alla rader som börjar på detta vis, med ett ord efterföljt av ett kolon kallas för label. En label är alltid förknippad med en adress.
    Detta gör t.ex. referering till en variabel mycke lättare, eftersom man inte behöver veta adressen för variabeln utan använder istället motsvarande label. Likaså används labels när man vill göra programslingor.
    main-labeln har dessutom en speciell funktion, nämligen att ange startpunkten för programmet. När man startar exekveringen av programmet kommer MISSE att söka redapå just denna main-label och påbörja exekveringen därifrån.
  • .globl main
  • Gör main-labeln till en global label. Funktionsmässigt har detta ingen betydelse för program som nu just simuleras i MISSE, men för den goda konventionens skull så lönar det att lära sig bra mips-programmerings-etikett :-)
  • jr $31
  • En instruktion som hoppar till den adress som finns angiven i register 31 (return address).
  • nop
  • En No Operation-instruktion, dvs. instruktionen gör ingenting. Instruktionen krävs dock här eftersom alla hopp-instruktioner (jr ovanför) kräver att det alltid finns en instruktion i hopp-luckan (instruktionen efter en hopp-instruktion).

    Som du säkert redan lagt märke till så finns det enbart två instruktioner i den färdiga program-mallen. Dessa två instruktioner används till för att berätta åt MISSE att det är dags att avluta programmet. Precis, en vanlig dator skulle inte veta att vi vill avsluta programmet utan att vi meddelar om saken. Och det är precis vad dessa två instruktioner i detta fall gör.
    När man antingen utfört en kompilering (med Compile-knappen) eller en Reset så kommer du att märka att register 31 (ra) innehåller värdet 0x40000000. Detta är dit programmet kommer att hoppa, och eftersom där för tillfället finns inga instruktioner så kommer MISSE att avluta exekveringen.

    Nu är det förståss ingenting intressant med ett program som omedelbart avslutar när man exekverar det, så låt oss sätta till ett par instruktioner som gör någonting.

    2.2 Första programmet

    Vi ska börja med att under "--- insert code here"-raden infoga följade tre rader : (vad dessa rader gör kommer vi till snart)
        addi    $8, $0, 15
        addi    $9, $8, 1
        addi    $9, $9, -1
    

    Vårt fullständiga program ser då ut på följande vis :
    /*
     * New file
     */
    
    #include <iregdef.h>
    
    	.data # address at 0x10000000
    
    # --- insert variables here
    
    	.text # address at 0x00400000
    	.globl main
    main:
    
    # --- insert code here
    
    	addi	$8, $0, 15
    	addi	$9, $8, 1
    	addi	$9, $9, -1
    
    	jr $31
    	nop
    

    2.3 Exekvering av ett program

    Nu är det dags att testa köra programmet i MISSE.
    Först måste vi kompilera programmet med Compile från vertygslådan. Det kan hända att kompileringen avbröts med ett fel-meddelande i Status-fönstret. Korrigera dessa eventuella fel och prova kompilera pånytt. Rader i Status-fönstret som börjar med Warning behöver inte beaktas ännu. Dessa kan bl.a. bero på brister i själva MISSE som inte ännu korrigerats.
    Nu är det bara att starta exekveringen med Run.

    När programmet exekverats färdigt kommer du att märka att tre rader i Register-vyn har markerats med rött respektive grönt. Grön färg indikerar att dessa register har modifierats nångång under exekveringen, medan röd färg anger det senast modifierade registret.

    Dessa tre rader är då register $0, $8 samt $9.
    Register $8 modifierades av den första addi-raden, medan register $9 av den andra och tredje addi-raden.

    Vad är det då som har modifierat register $0?
    Jo, tittar vi på sista instruktionen, nop, så är denna instruktion en pseudo-instruktion och motsvarar i själva verket sll $0, $0, 0  (nop är förövrigt den enda godkända pseudo-instruktionen i MISSE).
    Här ser vi att sll-instruktionen lagrar resultatet i register $0.

    Var det inte så att register $0 aldrig kunde modifieras?
    Helt riktigt. Register $0 kan inte ändra värde från 0, så vad vi än lagrar dit så kommer det fortfarande att ha värdet 0. MISSE kommer dock ändå att visa skrivningar till register $0 med röd färg i Register-vyn.

    Vad är det då som dessa tre nyligen inmatade instruktioner gör?
    Vi ska låta MISSE svara på den frågan.

    2.4 Stegvis exekvering med Step

    För att vi ska kunna titta närmare på vad som sker instruktion för instruktion i programmet så kan vi välja att använda Step-knappen. Först måste vi dock utföra Reset i MISSE för att denna Step-knapp skall bli tillgänglig.

  • Steg 1 -- utför en Reset
  • Steg 2 -- tryck på Step för att exekvera första instruktionen.

    Du kommer att märka att Instruction View-fönstret hoppar fram. Detta fönster visar den kompilerade källkoden som op-koder samt vilken adress dessa finns lagrade på i minnet (mera om detta i kap 1.5).

    Nu har även instruktionen addi $8, $0, 15  exekverats och dess resultat syns i register $8 som värdet 0000000f, dock bör man komma ihåg att Register-vyn visar värdena i hexadecimal notation.
    Instruktionen har alltså lagrat värdet 15 i register $8, vilket stämmer bra överens med instruktionens funktionalitet.
    addi $8, $0, 15  tar nämligen värdet ur andra argumentfältet, register $0 i detta fall, adder det med värdet i fält 3, dvs. 15. Resultatet lagras sedan i fält 1, vilket är register $8.

  • Steg 3 -- tryck på Step igen

    addi $9, $8, 1  kommer att ta värdet ur register $8, som är 15, adderar till 1 och sedan lagrar resultatet i register $9, vilket syns i Register-vyn hexadecimalt som 00000010, dvs. 16.

  • Steg 4 -- tryck på Step igen, för 3:e gången

    addi $9, $9, -1  minskar värdet i register $9 med 1.

    Nu är det bara två instruktioner kvar; jr $31 och nop, vilka förklarades tidigare.
    Dessa kan du skippa genom att klicka två gånger på Step eller en gång på Run.

    Stegvisa exekveringen är nu klar.

    <--- Tillbaka

    MIPS is a registered trademark of MIPS Technologies, Inc.             Senast uppdaterad 26.10.2004