Laboration:. Jämförelser mellan assembler och C. CPU ACCA ACCD ACCB 8-bitars ackumulatorer eller 16- bitars ackumulator CCR 1 1 1 SXH I NZVC Flaggregister Carry/Borrow IX IY PC Indexregister X Indexregister Y Overflow Zero Negative I-interrupt mask Halfcarry (from bit 3) X-interrupt mask STOP disable Programräknare SP Stackpekare I denna laboration ska vi se hur datorns CPU används för att göra enkla datamanipuleringar och enkla beräkningar. För assemblerprogrammeraren ingår CPU:n i det som brukar kallas programmerarmodellen. För att skriva program i assembler måste man ha goda kunskaper i hur och flaggor används. Om man använder högnivåspråk befrias man däremot från att känna till alla dessa detaljer. Det är kompilatortillverkaren som får sitta inne med dessa kunskaper. Men vid exempelvis felsökning är det viktigt att förstå hur ett program använder de olika registren. I laborationen ska vi se på några enkla programexempel som använder. Vi ska också se hur man med högnivåspråket C utför motsvarande uppgifter och hur kompilatorn utnyttjar CPU:n. Stefan Nyman, MICRONYM
Förberedelser: Alla uppgifter i denna laboration kan du lösa med hjälp av kompendiet Bygg och programmera. Speciellt läsvärt är kapitel 2 och 3. Använd också gärna databoken HC11 M68HC11E Family, Technical Data. Alla åtta förberedelseuppgifter ska vara gjorda vid laborationens början. Vissa av laborationsuppgifterna kan också göras i förväg. Uppgifter: Ta reda på följande: 1. Vilken assemblerinstruktion används för att lägga ett visst värde i ackumulator A?.. 2. Vilken instruktion kopierar värdet i ackumulator B till ackumulator A?.. 3. Hur kan man multiplicera innehållet i en ackumulator med 2?.. 4. Med vilken instruktion kan man beräkna skillnaden mellan värdena i ackumulatorerna?.. 5. Vad menas med indexerad adressering?... 6. Med vilken instruktion kan man addera ett 8-bitarstal med ett 16-bitarstal?... 7. Vad har flaggregistrets Z-flagga för funktion?... 8. Vad är skillnaden mellan instruktionerna ldx #$5 och ldx $5?... 2
Laborationsuppgifter: Uppgift 1. Ackumulatorer. Öppna projektet Uppgift1.prj. Skriv ett assemblerprogram i filen CPU1.s07 som utför följande i en oändlig loop: Lägg talet 5 i ackumulator A. Kopiera det till ackumulator B. Multiplicera det ena med 4 och det andra med 2. Detta går att göra utan att använda multiplikationsinstruktion! Addera talen! Avsluta med instruktionen: staa $1004 Kör programmet i full fart. Vad blir resultatet av additionen? Stoppa programmet. Öppna fönstret som visar och följ vad som händer när du stegar instruktion för instruktion. Starta från början. Vilka register förändras under programmets gång? Ovanför flaggregistret står det SXHINZVC. Vad betyder Z och C? Lägg in en instruktion i programmet så att Z ettställs! Lägg in en instruktion i programmet så att C ettställs! 3
Uppgift 2. Läs ur minnet med indexregister. Använd det färdiga projektet Uppgift2.prj. Komplettera CPU2.s07 med ett program som gör följande: Läs av vilka värden som ligger i området $0000-$0007. Använd X-registret för att peka ut värdena. Varje värde ska i tur och ordning skrivas på adress $1004. När programmet skrivit ut det sista värdet ska det stoppa. Stega igenom programmet och iaktta vad varje instruktion gör. Vilka värden ligger på adresserna 0000-0007? Varför? Använd debuggerns Memory Window för att ändra på några värden. Stega från början igen och följ förändringarna i flaggregistret! Kan du se om någon instruktion påverkar Z-flaggan? I så fall vilken? Vilka övriga instruktioner i programmet påverkar Z-flaggan? Förklara vad assemblerdirektivet FCB betyder. 4
Uppgift 3. Läs ur minnet C-program. När man skriver program i högnivåspråk är det mycket osannolikt att man vill eller behöver känna till de verkliga adresserna till en dataarea. I exemplet i uppgift 2 kunde man ju också använda namnet före datafältet, så man kunde nå det utan att referera till absolutadresser. Utgå från projektet med namnet Uppgift3.prj. Det innehåller två filer, CPU2.c och cstartup.s07. Komplettera while-satsen och resten av huvudprogrammet. Ladda ner och stega igenom så att du får alla siffrorna i tur och ordning på displayen. Öppna följande fönster: Register window, Memory window och Watch window. På vilken adress ligger variabeln i? Studera noga hur kompilatorn hanterar fält och index. Denna kompilator använder också register X för att nå ett speciellt element i fältet. Med hjälp av indexvärdet i och startadressen för fältet data beräknas adressen med fem instruktioner. Vilka är det?... Ändra fältdeklarationen till const unsigned char data[] = {10,20,30,40,50,60,70,80}; På vilken adress ligger nu variabeln i och var finns fältet med 8 värden? Nu beräknas adressen i X på ett annat sätt. Vilka instruktioner gör detta?... Ändra i programmet så att i blir en 16-bitarsvariabel. Hur beräknas nu adressen i X?... 5
Uppgift 4. Beräkning av medelvärde. Utgå från uppgift 3. 1. Spar projektet med nytt namn: Uppgift4.prj. 2. Spar CPU2.c med nytt namn: medel.c. 3. Byt ut under Projekt/Files: CPU2.c medel.c. Skriv om huvudprogrammet så att det beräknar medelvärdet av de åtta talen som ligger i fältet data. Du kan behöva en variabel för summan. Provkör och titta på assemblerkoden. Hur utförs divisionen i medelvärdesuträkningen?... Lägg till ett nionde element till fältet och beräkna medelvärdet på de nio. Hur utförs nu divisionen?... Ta bort ett element i fältet; d.v.s. återställ fältets storlek till 8 platser. Låt fortfarande medelvärdet beräknas som om det hade nio element. Vad händer?... Det finns anledning att varna för att C-språket inte är så säkert att hantera. Man måste noga kolla index och gränser och framför allt inte glömma att det första elementet i ett fält har nr 0! Uppgift 5. Beräkning av medelvärde i assembler. Skriv ett program i assembler som beräknar medelvärdet av nio tal som ligger fr.o.m. adress $0000. Skapa ett projekt Uppgift5.prj och en assemblerfil, medel.s07. Utgå från samma dataarea som i uppgift 2.... 6
Uppgift 6. Talcirkeln. Nytt projekt: Uppgift6.prj med assemblerfilen talcirkel.s07. Stega detta omfattande program och notera när flaggorna N, Z, V och C ändrar värde. Vilken av flaggorna ändrar sig inte?... Instruktionen inca kan bytas ut mot en annan utan att programmets funktion förändras, men så att alla fyra flaggor påverkas. Vilken instruktion gör samma jobb som inca?... Byt ut inca mot denna instruktion och fyll i nedanstående: N ettställs när ackumulator A ändrar värde från... till... N nollställs när ackumulator A ändrar värde från... till... Z ettställs när ackumulator A ändrar värde från... till... Z nollställs när ackumulator A ändrar värde från... till... V ettställs när ackumulator A ändrar värde från... till... V nollställs när ackumulator A ändrar värde från... till... C ettställs när ackumulator A ändrar värde från... till... C nollställs när ackumulator A ändrar värde från... till...... Ytterligare en flagga ändras lite då och då. Vilken? Varför?... 7