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.
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: