Laboration:. Jämförelser mellan assembler och C. I denna laboration undersöker vi hur aritmetiska beräkningar utförs. Vi tittar på olika variabeltyper: 8-bitars, 16-bitars, 32-bitars och flyttal. Förberedelser: Förklaringar till hur man deklarerar variabler i assembler och C står att läsa i BoP kap. 3.3 resp. kap. 8.1. Uppgifter: 1. Ange de assemblerdirektiv som behövs för att reservera utrymme för en 8- bitarsvariabel data8 på adressen $0005....... 2. Motsvarande i C: Deklarera en 8-bitarsvariabel. I C vill och bör man inte styra variabler till speciella fysiska adresser. Detta sköts i.xcl-filen... 3. I vilket register hamnar produkten vid instruktionen MUL?.. 4. I vilka register hamnar kvoten resp. resten vid instruktionen IDIV?.. 5. Hur många bitar upptar följande variabeltyper hos 68HC11? char int float......... Stefan Nyman, MICRONYM
Laborationsuppgifter: Uppgift 1. 8-bitarstal. Använd det färdiga Uppgift1.prj och komplettera Add8.s07 så att programmet utför: summa = summa + tal1 För 8-bitarsaddition kan man använda: ADDA, ADDB eller ABA. Skriv först programinstruktioner som använder ADDA. Kompilera och provkör! Ändra värdet i tal1 med minnesfönstret. På vilka adresser ligger variablerna? Ändra programmet och använd additionsinstruktionen ABA istället. Det ser då ut såhär: Byt ut filen Add8.s07 mot Add8.c i projektet. Lägg till filen cstartup.s07. Komplettera Add8.c så du får en motsvarighet till assemblerversionen. Kompilera och ladda ner! Hur har C-satsen översatts? 2
Uppgift 2. 16-bitarstal. Om talområdet är 16 bitar, kan en processor som 68HC11 utföra beräkningar effektivt. Den innehåller ju instruktioner för 16-bitarsaritmetik. Ett nytt projekt med ny källkodsfil får du på följande sätt: 1. Spara projektet under nytt namn: Uppgift2.prj. 2. Spar Add8.c med namnet Add16.c. 3. Byt ut (där du anger vilka filer som ska vara med) filen Add8.c mot Add16.c. (Dessa tre steg är gångbara genom hela labbkursen när du vill ha nytt projekt med nya filer.) I filen Add16.c ska nu 8-bitarsvariabler bytas till 16-bitars. Ge också variabeln ett startvärde: tal1 = 33. På vilka adresser ligger de två variablerna? Hur får variablerna sina startvärden? Undersök detta genom att ställa om visningen till assembler och sen återstarta programmet (klicka på Reset). Var ligger de startvärden variablerna ska ha innan de initierats? Skriv assemblerinstruktionerna som motsvarar summa = summa + tal1. Du ser att du ganska lätt skulle kunna skriva en egen assemblerversion av 16- bitarsadditionen. 3
Uppgift 3. 32-bitarstal. Ändra variabeltypen så att du räknar med 32-bitars heltal. Initiera tal1 med ett rejält stort värde! Kompilera och stega igenom programmet i assembler-läge. Se till att du förstår hur additionen görs. Uppgift 4. En liten undersökning av flyttal. Ändra variabeltypen till flyttal. Startvärde för tal1: 3,375 Studera assemblerkoden! Hur kodas talet 3,375? Fyll i! +/- exponent excess-127 signifikand 3,35710 = 11.0112 = 1.10112 2 +1 (normerad form) Flyttal i enkel precision kodas såhär: Teckenbit: 1=negativt Exponent (8 bitar): talets exponent + 127 Signifikand (23 bitar): Talets värdebitar till höger om binärpunkten. Uppgift 5. Hur processorn hanterar multiplikation. Skriv ett litet program i assembler som multiplicerar två 8-bitarstal och placerar produkten i en 16-btarsvariabel produkt. tal1 rmb 1 tal2 rmb 1 produkt rmb 2 Skriv in några olika värden med hjälp av minnesfönstret. Skriv motsvarande program i C. 4
Använd typen unsigned char för de två talen som multipliceras och unsigned int för kvoten. Studera den assemblerkod som skapats. Jämför med det du skrev direkt i assembler. Ser du några likheter? Hur stor är koden som laddats ner till emulatorn? (titta i fönstret Report ) Ändra nu i källkoden så att typen signed används! Hur stor är nu koden som laddats ner till emulatorn? Stega igenom ett varv i programmet! Vad har hänt? Uppgift 6. Hur processorn hanterar division. Det finns ett färdigt assemblerprogram som du kan använda i denna uppgift. Det heter Division.s07. Lägg märke till att i detta exempel provar vi med olika konstanta värden som laddas in i registren före divisionen. Man hade naturligtvis också kunnat göra på samma sätt som i de tidigare uppgifterna. tal1 och tal2 är nu inga variabler (de ligger inte i variabelminnet), utan är nu bara symboler för varsin konstant. Provkör detta i ett nytt projekt! Vilket värde har kvoten resp. resten? Kvot =... Rest =... Ändra så att tal2 = 0. Vilket värde får nu kvoten? Assemblerinstruktionen hanterar kvot och rest på ett behändigt sätt. 5
Låt tal1 vara = 21 och tal2 = 8. Vad blir nu resten? Om vi nu fortsätter att dividera resten med 8 med hjälp av divisionsinstruktionen FDIV (fractional divide) får vi fram siffrorna till höger om binärpunkten. Skriv in instruktionerna ldx #tal2 fdiv efter instruktionen stx kvot. Hur ska man tolka värdet i X-registret efter instruktionen fdiv? Det finns också ett färdigt C-program Division.c. Testa det i ett C-projekt och studera hur kompilatorn översätter koden. I C finns också en operation som ger resten. Byt ut divisionen mot denna och se efter hur assemblerkoden blir. I C finns ingen motsvarighet till HC11:s FDIV. Vi ser att beräkningar kan göras mycket effektivt i assembler om man har god kännedom om processorns uppbyggnad. Byt ut variabeltypen mot signed int. Studera koden som skapas. Varför blir det så mycket mer kod? 6