Prof. Dr. K. Wüst FH Gießen–Friedberg, FB MNI WS 2006/2007 Studiengang Informatik Rechnerarchitektur 2. Hausübung mit Lösungen Unterprogramm für eine CPU08 Für einen Spannungsteiler mit zwei Widerständen R1 und R2 gilt: Uges = R1 + R2 U2 R2 Schreiben Sie für einen Mikrocontroller der 68HC08-Reihe mit CPU08-Prozessor ein Unterprogramm, das diese Berechnung durchführt. Die Schnittstelle des Unterprogramms soll wie folgt aussehen: Bei Aufruf: U2 wird in Register A übergeben Bei Rückkehr: Das Ergebnis Uges wird in Register A zurückgegeben R1 und R2 sind 8-Bit-Variablen, die im Datenbereich angelegt und mit den richtigen Werten belegt sind; sie sollen bei Ausführung des Unterprogrammes benutzt werden. Es soll durchgehend mit positiven (vorzeichenlosen) Zahlen gerechnet werden. Dabei werden unvermeidliche Rundungsfehler auftreten. Aufgaben 1) Implementieren Sie ein entsprechendes Unterprogramm für die CPU08. Nutzen Sie dabei die arithmetischen Befehle der CPU möglichst gut aus. Vorüberlegungen Zur Berechnung des angegebenen arithmetischen Ausdrucks sind drei arithmetische Operationen notwendig, mit denen schrittweise das Ergebnis aufgebaut wird. Beim Programmentwurf sollte man Vorüberlegungen anstellen: a) Die Addition; sie könnte zu einem Übertrag (Carry) führen, wenn die Zahlen zu groß sind. Für die momentan angegebenen Zahlenwerte ist die Addition unkritisch, 8 Bit reichen aus. Für den Fall späterer Programmänderungen (R1 , R2 ) könnte man das Carryflag überprüfen. b) Ablauf auf der CPU08: Multiplikator in A, Multiplikand in X, Ergebnis in X-A. Maximalwerte: X=255, A=255, X-A=65025. Die Multiplikation ist unkritisch, da das Registerpaar X-A immer ausreicht um das Produkt zweier 8-Bit-Zahlen aufzunehmen. c) Ablauf: Dividend in H-A, Divisor in X, Ergebnis in A, Rest in H. Maximalwerte: HA=65535, X=255, A=255, H=254. Die Division ist kritisch; sie darf nicht auf zu große 2.Hausübung Rechnerarchitektur - Prof. Dr. K. Wüst 2 Ergebnisse führen da für das Ergebnis nur ein 8-Bit-Register (A) zur Verfügung steht. Wenn das Divisionsergebnis in A zu klein ist, gibt es ebenfalls ein Problem: Es bleibt ja ein Rest, der nicht mehr geteilt werden konnte. Der Rest kann maximal Divisor-1 sein. Für ein korrektes Ergebnis müsste dieser Rest noch durch den Divisor geteilt werden. Die Wertigkeit eines vernachlässigten Restes kann sich daher der 1 annähern, was bei kleinem Divisionsergebnis prozentual ein sehr großer Fehler ist. Daran muss sich die Reihenfolge der Operationen ausrichten. Beispiel: x x x x = = = = R1 ; x=30 x + R2 ; x=180 x/R2 ; x=1 (!?) x*U2 ; ... Da R1=30 und R2=150 wird im dritten Schritt 180/150 gerechnet, das Ergebnis ist zu klein, nämlich 1, und enthält einen Fehler von ca. 17%, der sich nur mit aufwändiger Auswertung des Divisionsrestes wieder gutmachen lässt. Eine bessere Reihenfolge ist: x x x x = = = = R1 x + R2 x*U2 x/R2 Hier entstehen Zahlen, die vom Prozessor mit ausreichender Genauigkeit verarbeitet werden können. Beispiel: Für R1=30, R2=150 und U2=199 ergibt sich ein Ergebnis von 238 x x x x = = = = R1 ; x=30 x + R2 ; x=180 x*U2 ; x=35820 x/R2 ; x=238, Rest 120 Der Rest kann maximal (Teiler-1) sein, also hier 149. Das entspricht einem Nachkommaanteil von fast 1. Dann hat man einen relativen Fehler von ca. 1/240, also 0.4 %. Das ist nur ein kleiner Fehler, die Berechnungsreihenfolge ist also für größere Werte von U2 akzeptabel. Bei kleinen Werten für U2 wird aber das Divisionsergebnis wiederum sehr klein und der relative Fehler steigt an. Bei U2=1 ergibt sich x x x x = = = = R1 ; x=30 x+R2 ; x=180 x*U2 ; x=180 x/R2 ; x=1 Da das mathematisch korrekte Ergebnis 1.2 ist, liegen auch hier wieder ca. 17% Fehler vor. Damit ist Frage 3 schon in der Entwurfsphase beantwortet. Für kleine Spannungswerte U2 ist der Berechnungsgang also sehr ungenau, je nach Applikation aber tolerierbar. Eine Implementierung in CPU08-Assembler muss für Addition, Multiplikation und Division immer die Zwischenergebnisse in die richtigen Register bereit legen. Dies kann z. B. über den Stack erfolgen. 2.Hausübung Rechnerarchitektur - Prof. Dr. K. Wüst 3 Beispiel-Lösung ; ; ; ; ; ; ; ; ; ; ; ; ; ************************************************************* Unterprogramm Uges Uges = (R1+R2)/R2 * U2 Eingabe: Parameter: U2 in A, maximal 212 R1 und R2 auf Speicherplätzen mit genau diesem Variablennamen Ausgabe: Bei Rückkehr aus dem Unterprogramm Ergebnis in A ************************************************************* Uges: psha ; lda R1 ; add R2 ; bcs Fehler pulx ; mul ; pshx ; pulh ; ldx R2 ; div ; ; bcs Fehler rts Fehler: retten auf Stack R1 in Akku laden Akku enthält R1+R2 ; Carryflag zeigt Überlauf bei Addition an Um von Stack holen in Register X X-A enthält U2*(R1+R2) X nach ... H bringen X=R2 A = U2*(R1+R2)/R2 Ergebnis liegt in A, Rest in H ; Carryflag zeigt Überlauf bei der Division an ; Fehlerbehandlung hier ergänzen rts 2) Geben Sie an, mit wie vielen Byte der Stack bei Ausführung des Programmes maximal belegt ist. Lösung Bei Aufruf des Unterprogrammes wird die Rücksprungadresse auf den Stack gelegt (2 Byte). Da im Unterprogramm nach jedem PUSH-Befehl auch wieder ein PULBefehl folgt, beträgt die maximale Stackbelegung 3 Byte. 3) Geben Sie an, für welchen Wertebereich von U2 ein (im Rahmen der Rundungsfehler) richtiges Ergebnis berechnet wird, wenn R1=30 und R2=150 ist. Lösung Das Ergebnis wird gemäß Aufgabenstellung im Register A zurückgegeben kann also maximal den Wert 255 haben. Im Maximalfall gilt also: Uges = R1 + R2 U2 = 255 R2 2.Hausübung Rechnerarchitektur - Prof. Dr. K. Wüst 4 Aufgelöst nach U2 ergibt sich U2 = 255 R2 150 = 255 = 212.5 R1 + R2 180 Der maximale Eingabewert für U2 der noch korrekt verarbeitet wird ist 212. Man kann das ausprobieren, im oben angegebenen Programm entsteht bei größeren Werten ein Überlauf (CF=1) beim Divisionsbefehl. 4) Geben Sie an, welchen prozentualen Rundungsfehler das Ergebnis enthält, wenn R1=30, R2=150 und U2=1 ist. Lösung Gemäß Vorüberlegungen 20 %. (siehe oben) Tipps • Laden Sie sich das Handbuch der CPU08 herunter aus dem e-study-Portal im Kurs Rechnerarchitektur unter Literatur“. ” • Beachten Sie, dass bei der Multiplikation und Division mehrere Register beteiligt sind. Lesen Sie dazu die Beschreibung der Befehle MUL und DIV im Handbuch. • Laden Sie sich die CodeWarrior-Entwicklungsumgebung (CodeWarrior Development Studio for HC08 Microcontrollers, Windows-Version) vom Hersteller Freescale von der URL http://www.freescale.com/webapp/sps/site/overview.jsp?nodeId=01272600612247 herunter und testen Sie Ihren Entwurf mit dem Simulator aus! Der Link ist im Kurs Rechnerarchitektur des e-study-Portals vorhanden, Sie müssen sich aber vor dem Downlaod registrieren. Um ein Assemblerprogramm einzugeben und zu starten machen einfach Sie folgendes: 1. File / New... 2. HC(S)08 New Project Wizard 3. Project name: Hier einen Projektnamen eingeben 4. Please choose the set of languages to be supported: Assembly 5. select the derivative you would like to use: HC08 / G-Family / 68HC908GP32 und connection: Full chip simulation 6. Add existing files to the project: keine (gleich weiter) 7. Rapid Application Development Options: None 8. Fertig stellen 9. Doppelklick auf File main.asm“ ” 10. Zum Debuggen klicken Sie einfach auf das Symbol mit dem Käfer. Dort finden Sie im Menü Run“ weitere Befehle, wie Start, Single Step und Restart. ”