AVR Assembler: 8-Bit-Arithmetik und mathematische Tricksereien

Immer wenn harte Echtzeitanforderung, hardwarenahe Programmierung und Ressourcenknappheit in einem Projekt relevant sind ist der Einsatz von Assembler bei der Softwareentwicklung unerlässlich. Dies trifft besonders im Umfeld von Mikrocontrollern und embedded system zu.
Grafikdaten im Programmspeicher eines AVR Mikrocontroller
Bei der Optimierung können jedoch ganz unterschiedliche Aspekte zum Tragen kommen. Je nach Anwendungsfall unterscheidet man:
Laufzeitoptimierung schnelle Ausführung und Berechnung (bei Echtzeitsystemen definierte Antwortzeiten)
Speicheroptimierung ressourcenschonender Umgang mit dem meist geringen Arbeitsspeicher bzw. Stack
Programmspeicheroptimierung Reduktion der Programmgröße bei der Verwendung kleiner Controller und Systeme
Häufig gehen Optimierungen in einem Bereich zu Lasten anderer Ressourcen. Zur Veranschaulichung sind die Codefragmente in kleinen Testanwendungen zusammengefasst. Als Testsystem wird ein ATiny13a (Sparrow) verwendet. Die Listings sind auf allen Controller der AVR-Familie und mit Anpassungen auf anderen Architekturen verwendbar. Hier soll eine Sammlung bekannter Verfahren und mathematischer Tricksereien entstehen.
Division und Multiplikation mit 2er Potenzen (Programmspeicheroptimierung)
Die Tiny-Serie der AVR Mikrocontroller kennt keine Befehle für Division oder Multiplukation. Das ist soweit kein Beinbruch das Problem lässt sich ja auch in Software lösen. Besonders platzsparend und effizient wird die Sache allerdings wenn man seine Berechnungen auf 2er Potenzen reduzieren kann. Also teilen oder multiplizieren mit 2, 4, 8, 16 ...
Im Binärsystem ist Dividieren oder Multiplizieren durch/mit 2 nichts anderes als ein Shift nach rechts bzw. links. Im 10er System verwenden wir diesen Trick ebenso wenn wir mit 10, 100, 1000 multiplizieren. Beim Teilen verschieben wir einfach das Komma. Pro Funktion kommt man mit gerade mal 4 Befehlen aus.
Häufig lässt sich eine Rechnung mittels Annäherung auch komplett auf Potenzen umstellen. Dabei sollte man die Genauigkeit im Auge behalten. Mit einem angehängten rol/ror (Rotation links/rechts) kann die Funktion auch auf 16Bit und mehr erhöht werden. Hier wird das rausfallende geschiftet Bit aus dem Carry-Bit für das nächste Byte gerettet.
Registerinhalte tauschen mit EOR (Speicheroptimierung)
AVR Mikrocontroller verfügen über 32 Register. Die meisten Operationen und Befehle sind allerdings nur auf die oberen 16 Register anwendbar. Bevor man die Daten auf dem Stack oder im RAM zwischenspeichert kann es sinnvoll sein die unteren Register (R0 - R15) als Zwischenspeicher zu verwenden. Dies geht am elegantesten mit XOR (EOR).
Die Lösung mittels XOR ist genauso schnell wie ein klassischer Dreieckstauch kommt aber ohne Hilfsregister aus.
Links und Referenzen: