Unterrichts- und Lernmaterial für Mikrocontroller
Unterrichts- und Lernmaterial fürMikrocontroller

8-Bit Arithmetik - Teil 1

In Kapitel AVR-Assembler - Teil 1 wurden bereits einfache Additionsbefehle vorgestellt. In diesem Kapitel geht es unter anderem um die arithmetischen Instruktionen: ADD (Addition), SUB (Subtraktion), NEG (Negation), CP (Vergleich), INC (Increment oder erhöhe um 1), DEC (Dekrement oder erniedrige um 1) und COM (1-er Komplement).

Übung 1 - Addition - Instruktionen ADD, COM

In dieser Übung wird gezeigt, wie man zwei 8-Bit Zahlen addiert. Dazu wird ein ATmega8 auf dem STK200 Board verwendet. Als optische Hilfe wird die Bargraf-Anzeige genutzt und das Ergebnis in binärer Form dargestellt.

 

Wer nicht (mehr) vertraut ist mit dem binären Zahlsystem, sollte sich das vorher noch einmal anschauen. Insbesondere, wie zwei Dualzahlen addiert, subtrahiert und multipliziert werden.

Bevor es an die Programmierarbeit geht, wird erst einmal das Datenblatt des ATtiny8 befragt. Gib eine Antwort auf die folgenden beiden Fragen:

  • Welche arithmetischen Rechenbefehle stellt der Controller laut Datenblatt zur Verfügung? Schaue hierzu im Instruction Set Summary nach.
  • Welche Grundrechenoperation wird nicht bereit gestellt?

 

Antworten:

Es sind über 10 OP-Codes im Datenblatt unter der Rubrik "arithmetic and logic instructions" zu finden.

Ein Befehl für die Division ist nicht angegeben.

Die in diesem Kapitel benutzten neuen Assembler-Instruktionen zeigen die nachfolgenden Tabellen 1a und 1b.

Tabelle 1a - Nur die rot markierten Flags werden von einer Instruktion bei Aufruf verändert.
Tabelle 1b - Nur die rot markierten Flags werden von einer Instruktion bei Aufruf verändert.

Bemerkungen zu einigen Flags im SREG

  • Z-Flag
    Wird immer gesetzt bei einem Null-Ergebnis bei einer arithmetischen oder logischen Operation.
  • C-Flag
    Das Übertrags-Flag. Es wird immer gesetzt bei einem Übertrag bei einer arithmetischen oder logischen Operation.
  • N-Flag
    Das N-Flag zeigt ein negatives Ergebnis (Bit 7 ist 1) bei einer arithmetischen oder logischen Operation an.
  • H-Flag
    Das Halbübertrags-Flag zeigt bei einigen arithmetischen Operationen einen Halbübertrag (Übertrag von Bit3 im lower nibble zu Bit4 im upper nibble) an.
  • V-Flag
    Dieses Überlauf-Flag unterstützt die 2-er Komplement Arithmetik.
  • S-Flag
    Das S-Flag ist immer das Ergebnis aus der logischen Verknüpfung von S XOR V (XOR -> exklusives ODER).
Übung 1 - Addition
Material
  • 1x STK200 mit Steckernetzteil und ISP2
  • Datenblatt des ATmega8
Aufgabe
  • Lege ein neues Projekt rechnen1 an
  • Gib das Assemblerprogramm addition.asm in den Editor ein und speichere es ab.
  • Brenne das Programm in den Controller und starte es anschließend.
  • Überprüfe, ob auf der Bargraf-Anzeige LED1 und LED2 leuchten. Abb. 1 zeigt das Ergebnis.

Schaltungsaufbau

Hat man kein STK200 Board zur Verfügung, lässt sich die Schaltung mit acht LEDs separat auf einem Steckbrett aufbauen.

 

 

 

 

 

Abbildung 1

Separater Schaltungsaufbau mit 10 Segment Bargraf-Anzeige. Nicht gezeigt werden die peripheren Beschaltungen (Spannungs-versorgung, Abblockkondensatoren etc.) des Controllers.

Das Programm addition.asm

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Abb. 2

In dem Programm addition.asm wird im Initialisierungsblock der PORTB auf Ausgang geschaltet.

Im Hauptprogramm werden die beiden Zahlen 2 und 5 in die Speicher R19 und R20 geladen und anschließend addiert und die Summe in R20 abgelegt.

Nach Bildung des 1-er Komplements wird der Inhalt von R20 an PORTB (LEDs) ausgegeben.

Wie arbeitet das Programm addition.asm?

  1. Die drei Direktiven (.nolist, .include, .list) zu Anfang des Programms kennen wir bereits.
  2. Der Hauptteil beginnt mit LDI (Load Immediate). Er lädt eine 8-Bit Konstante mit dem Wert 2 direkt in das Register R19 und eine zweite Konstante mit dem Wert 5 in das Register R20.
  3. ADD (Add without Carry) addiert die Inhalte der beiden Register R19 und R20 und legt das Ergebnis in R20 ab. 
  4. Die Ausgabe des Ergebnisses erfolgt über eine Bargraf-Anzeige. Die LEDs leuchten genau dann, wenn sie auf 0 gezogen werden. Deshalb muss aus der Binärzahl 6 (Summe aus 2 und 4) 0b00000110 durch Komplementbildung (0 wird zu 1 und umgekehrt) 0b11111001 erzeugt werden. Das macht COM z2.
  5. Die Ausgabe erfolgt über die Bargraf-Anzeige, die mit PORTB verbunden ist. Von PORTB müssen alle Portpins auf Ausgang geschaltet werden. Dazu wird zspchr (R18) mit 1 gefüllt -> 0xFF und anschließend über OUT in das DDRB-Register geladen.

 

Über das in AVR-Studio integrierte Hilfe-Menü (Help - Assembler Help) lassen sich zu allen hier benutzten Operanden-Codes umfangreiche Hilfetexte mit Programmbeispielen aufrufen. Eine weitere Besprechung der Wirkungsweise dieser Operanden entfällt deshalb.

 

  • Mit 8-Bit lassen sich nur vorzeichenlose Zahlen von 0 bis 255 (0b1111_1111) darstellen.

 

Was ist zu tun, um zwei 16-Bit Zahlen addieren zu können? Das wird in nachfolgender Übung untersucht.

  • Mit 16-Bit lassen sich vorzeichenlose Zahlen zwischen 0 und 65.535,
  • mit 32-Bit zwischen 0 und 4.294.967.294 darstellen.

Übung 2 - Addition von 16-Bit Zahlen - Instruktionen: ADC, SER

Die Addition zweier 16-Bit Zahlen verläuft im Prinzip wie die von zwei 8-Bit Zahlen. Es werden zuerst die lower Bytes und anschließend die higher Bytes mit Carry addiert. Fertig.

Das Addieren mit Carry wird über ADC, das Addieren ohne Carry mit ADD aufgerufen. Ein Ablaufplan oder Pseudocode könnte so aussehen:

 

  • Addiere zahl1L und zahl2L (SummeLowByte)
  • Addiere mit Carry zahl1H und zahl2H plus Carry-Bit (SummeHighByte).
  • Gib auf der Bargraf-Anzeige das SummeHighByte aus.
Übung 2 - Addition zweier 16-Bit Zahlen
Material
  • 1x STK200 mit Steckernetzteil und ISP2
  • Datenblatt des ATmega8
Aufgabe
  • Lege ein neues Projekt addition2 an
  • Gib das Assemblerprogramm addition2.asm in den Editor ein und speichere es ab.
  • Brenne das Programm in den Controller und starte es anschließend.
  • Notiere, welche LEDs der Bargraf-Anzeige leuchten (1) und welche nicht (0).

Schaltungsaufbau

wie in Übung 1, Abb. 1.

Das Programm addition2.asm

Abb. 3 - addition2.asm mit den Instruktionen ADD, ADC, COM, SER

Wie arbeitet das Programm addition2.asm?

  1. Die drei Direktiven (.nolist, .include, .list) zu Anfang des Programms kennen wir bereits. Auch nicht neu ist die Direktive .equ. Über sie wird einer Variablen ein fester Wert zugewiesen.
  2. Der Initialisierungsteil beginnt mit LDI (Load Immediate). Es werden vier 8-Bit Zahlen (der Controller verarbeitet nur 8-Bit Zahlen!!!), je zwei Lowbytes und Highbytes der beiden 16-Bit Zahlen in vier verschiedene Register geladen.
  3. ADD (Add without Carry) addiert die Inhalte der beiden Lowbyte-Register R16 und R17 und legt das Ergebnis in R16 ab.
  4. ADC (Add with Carry) addiert die Inhalte der beiden Highbyte-Register R18 und R19 und legt das Ergebnis, unter Berücksichtigung des Carry, in R18 ab. 
  5. Die Ausgabe des Ergebnisses erfolgt über eine Bargraf-Anzeige. Die LEDs leuchten genau dann, wenn sie auf 0 gezogen werden (low active). Deshalb muss von der Binärzahl in R18 das Komplement gebildet werden. Das ist die Aufgabe von COM R16.
  6. Die Ausgabe erfolgt über die Bargraf-Anzeige, die mit PORTB verbunden ist. Von PORTB müssen alle Portpins auf Ausgang geschaltet werden. Dazu wird R20 mit Einsen gefüllt -> SER (Set all bits in Register) und anschließend über OUT in das DDRB-Register gesetzt. Über das Programm werden die 8 höchstwertigen Bits angezeigt.
  7. Für die Ausgabe der 8 niedrigwertigen Bits muss das Programm in zwei Zeilen geändert werden: com r16 und out portb, r16 muss es dann heißen.

Hat man das Prinzip verstanden, ist die Addition von beliebig großen Zahlen mit Assembler möglich und einfach durchzuführen. Im vorliegenden Beispielprogramm der Übung 2 werden die beiden Zahlen

  • 0xC2F3 oder dezimal 49907   und
  • 0x04BA oder dezimal 1210

miteinander addiert. Die Summe ist: 51117 oder 0b1100_0111_1010_1101. Die rot markierten acht Bit stehen für das Highbyte, die blauen acht Bit für das Lowbyte. Dreht man das STK200-Board um 90° nach rechts, so dass die Bargraf-Anzeige horizontal liegt, kann man die entsprechende Bitkonfiguration unmittelbar ablesen (siehe Abb. 4).

Abb. 4 - High- und Low-Byte der Summe zweier 16-Bit Zahlen.

Übung 3 - Subtraktion mit Unterlauf - Instruktionen SUB, NEG

Die Subtraktion zweier Zahlen kann

  • ein positives Ergebnis     oder
  • ein negatives Ergebnis (Unterlauf)

liefern. Das hängt davon ab, ob der Minuend größer oder kleiner als der Subtrahend ist. Wie wirkt sich ein Unterlauf in der Zahldarstellung aus? Das untersucht die folgende Übung 3.

 

Etwas Theorie zur Subtraktionsmethode

Die Subtraktion wird in dieser Übung zurückgeführt auf eine

  • Addition mit Zweierkomplementbildung.

Dazu werden alle Stellen des Subtrahenden -B negiert (Einerkomplement; Assemblerinstruktion: COM) und zu dem sich neu ergebenden Wert eine 1 addiert. Dadurch entsteht das Zweierkomplement /B + 1 des Subtrahenden (Assemblerinstruktion: NEG). Dieses entspricht der Zahl -B:

  • - B = /B + 1

Um mit vorzeichenbehafteten (signed) Zahlen arbeiten zu können, benötigt man ein Vorzeichenbit. Per definitionem ist dies das

  • MSB (most significant bit)

das am weitestens links stehende höchstwertige Bit; für die reine vorzeichenbehaftete Zahldarstellung stehen bei verfügbaren 8-Bit dann noch 7-Bit zur Verfügung. Der vorzeichenbehaftete Zahlenbereich erstreckt sich von

  • -128, ..., 0, ..., +127          oder allgemein

     
  • -2n-1, ..., 0, ..., +2n-1-1    mit n aus N, Anzahl der verfügbaren Bits

Ein Beispiel

 

Die Zahlen 0x03 (dezimal: 3) und 0x0D (dezimal: 13) sollen subtrahiert werden. Die Subtraktion wird durch eine Addition mit Zweierkomplementbildung ausgeführt.

  1. Minuend: 0x03 oder 0000 0011 bleibt unverändert
  2. Subtrahend: 0x0D oder 0000 1101
  3. Zweierkomplement: aus 0000 1101 wird 1111 0011
  4. Addition: 0000 0011 + 1111 0011 = 1111 0110
  5. Bit 7 enthält eine 1, sie signalisiert ein negatives Ergebnis. Bleiben sieben Bitstellen für die Differenz: 11 10110 (siehe Abb. 5; dies entspricht der Zahl -10).
  6. Ergebnis von 0x03 - 0x0D = 11 10110 oder -10

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Abb. 5

Die linke Spalte zeigt die positiven, die rechte die negativen Binärzahlen in der Zweierkomplent-Arithmetik. Das höchstwertige Bit (hier im Bild: Bit 4) signalisiert eine negative Zahl.

In Übung 3 werden wir die Zweierkomplementarithmetik praktisch anwenden.

Die Erläuterungen zum Programmablauf finden sich in den Kommentarzeilen des Programms.

Übung 3 - Subtraktion zweier 8-Bit Zahlen mit Unterlauf
Material
  • 1x STK200 mit Steckernetzteil und ISP2
  • Datenblatt des ATmega8
Aufgabe
  • Lege ein neues Projekt differenz1 an
  • Gib das Assemblerprogramm differenz1.asm in den Editor ein und speichere es ab.
  • Brenne das Programm in den Controller und starte es anschließend.
  • Notiere, welche LEDs der Bargraf-Anzeige leuchten (1) und welche nicht (0).

Schaltungsaufbau

wie in Übung 1, Abb. 1.

Das Programm differenz1.asm

Abb. 6 - Subtraktion mit Unterlauf (negativer Differenz)

Ergebnisausgabe auf der LED Bargrafanzeige eines STK200

 

 

Abb. 7

Die LEDs auf dem STK200 sind werksseitig active low geschaltet. Aus diesem Grund muss auf das Ergebnis das Einerkomplement angewendet werden. Es wird dann ohne Vorzeichen binär als 4 angezeigt.

Links neben der LED-Zeile stehen die Positionsbezeichner der LEDs: 0 - 7. Darunter etwas verdeckt: ISP (in-system-programming) und ON (Betriebsanzeige).

Läßt man die Instruktion

  • com r17

im Programm (siehe Abb. 6) weg, dann zeigt die LED Bargrafanzeige das folgende Bild:

 

 

 

 

 

Abb. 7b

Bei vorzeichenbehafteter Arithmetik zeigt  das STK200 bei negativer Differenz das Ergebnis "invertiert" an, wenn die Instruktion com r17 aus Programm differenz1.asm weggelassen wird.

Übung 4 - Instruktion BRCS

Was das folgende Programm der Übung 4 macht und warum, dass soll in dieser Übung geklärt werden. Dazu ist unbedingt das Instruction Set Summary notwendig. Die Kommentarzeilen im Quelltext des Programms geben ausführliche Hinweise.

Übung 4 - Instruktion BRCS
Material
  • 1x STK200 mit Steckernetzteil und ISP2
  • Datenblatt des ATmega8
Aufgabe
  • Lege ein neues Projekt differenz2 an
  • Gib das Assemblerprogramm differenz2.asm (siehe Abb. 8) in den Editor ein und speichere es ab.
  • Brenne das Programm in den Controller und starte es anschließend.
  • Notiere, welche LEDs der Bargraf-Anzeige leuchten und welche nicht.
  • Ändere anschließend das Programm ab, indem du die Werte von Minuend und Subtrahend vertauschst. Brenne das Programm in den Controller und starte es erneut.
  • Notiere, welche LEDs der Bargraf-Anzeige leuchten und welche nicht.
  • Erkläre mit eigenen Worten, wie das Programm arbeitet. Gib für jede Programmzeile eine Beschreibung, was die Instruktion bewirkt und ggf. warum der Befehl notwendig ist.
  • Warum wurde der Befehl BRCS gewählt? Gib eine Erklärung. Liesse sich auch ein andere Verzweigungsbefehl aus dem Instruction Set Summary auswählen? Begründe ggf. warum.

Das Programm differenz2.asm

Abb. 8 - Differenz2.asm Programm

Wie arbeitet das Programm differenz2.asm ?

Schauen wir uns dazu für jede aufgerufene Instruktion die Registerinhalte und Flags im AVR Simulator an.

 

1. Durchlauf - Minuend (0x09) kleiner als Subtrahend (0x0D) -> negatives Ergebnis

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Abb. 9a - Nach den ersten vier Instruktionen stehen in R16 (Subtrahend) -> 13, R17 (Minuend) -> 9 und in R20 -> 255. PORTB ist Ausgang. Im SREG sind keine Flags gesetzt. Der folgende Befehl ist SUB R17,R16.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Abb. 9b - Der fünfte Befehl führt die Subtraktion aus. Vier Flags im SREG (HSNC) sind gesetzt, da das Ergebnis negativ ist (Unterlauf). Der Inhalt von R17 zeigt die Differenz. Das Programm verzweigt nach diff_negativ, da Flag C gesetzt ist; der nächste Befehl ist NEG R17.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Abb. 9c - Die siebte Instruktion gibt das Ergebnis von R17 an den Ausgang PORTB, an dem die LEDs angeschlossen sind. Es leuchtet die LED an der Bitposition 2: 0000 0100. Dezimal entspricht das einer 4.

Da das Ergebnis negativ ist (Flag C ist gesetzt) und weil auf einem STK200 alle LE.Ds activ low geschaltet sind, leuchten auf einem STK200 alle LEDs, deren Pin auf LOW liegt. Dies gilt bis auf  PORTB.2 (liegt auf 1)  für alle anderen PORTB.x.

Für den zweiten Durchlauf werden die Zuweisungswerte für Minuendn und Subtrahend vertauscht

  • .EQU minuend = 0x0D
  • .EQU subtrahend = 0x09

Das Programm muss im Simulator neu assembliert und geladen werden, bevor man die Simulation starten kann. Die Ergebnisse zeigen die folgenden Screenshots.

2. Durchlauf - Minuend (0x0D) größer als Subtrahend (0x09) -> positives Ergebnis

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Abb. 10a - Nach den ersten vier Instruktionen stehen in R16 (Subtrahend) -> 9, R17 (Minuend) -> 13 und in R20 -> 255. PORTB ist Ausgang. Im SREG sind keine Flags gesetzt. Der folgende Befehl ist SUB R17,R16.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Abb. 10b - Der fünfte Befehl führt die Subtraktion aus. Im SREG ist kein Flag gesetzt (positives Ergebnis). Der Inhalt von R17 zeigt die Differenz. Das Programm verzweigt nicht, da kein Flag gesetzt ist; der nächste Befehl ist LDI R20,0xFF. .

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Abb. 10c - Die siebte Instruktion setzt alle Ausgangsleitungen PORTB.x auf 1 (EXOR-Verknüpfung), die eine 0 in R17 stehen haben. Das Ergebnis wird zurückgeschrieben in R17. Es leuchten auf einem STK200 nur die LEDs, die auf LOW liegen; das ist in diesem Fall bei PORTB.2 der Fall. Es wird die Zahl 4 angezeigt.

Druckversion | Sitemap
© Reinhard Rahner - Gettorf