Hi Zusammen! Ich programmiere nun schon länger in Assembler aber eines ist mir bis heute nicht richtig klar und ich habe auch keine antwort im net gefunden: Wofür Makros? Ich habe bisher öfter verwendete Programmstücke immer als Subroutinen angesprungen, somit wird der Code ja auch nur einmal programmiert... Bei Makros wird meines Wissens nach an der Stelle des Aufrufes das sich hinter dem Makro verborgene Programmstück eingeschoben, also benötigen mehrere Aufrufe ja auch mehr Speicher (ok, bei kleinen Sachen eher zu vernachlässigen)... Welche Vorteile kenn ich noch nicht und wann ist es sinnvoll Makros zu verwenden?
Am einfachsten kannst du das verstehen wenn du dir mal ein paar Beispiele anschaust: http://www.mikrocontroller.net/articles/AVR_Assembler_Makros Das Swap-Makro vertauscht 2 beliebige Register in 3 Zyklen. Die Register werden über Parameter übergeben; aus SWAP r15,16 wird so zum Beispiel:
1 | eor r15, r16 |
2 | eor r16, r15 |
3 | eor r15, r16 |
Eine solche allgemeine SWAP-Subroutine für beliebige Register wäre nicht möglich, oder nur mit sehr hohem Aufwand realisierbar (z.B. durch Übergabe der Registeradressen über den Stack und indirekte Adressierung der Register).
ich hab ja versucht es an Hand von beispielen zu verstehen :-) aber... dies setzt doch voraus das die Daten bereits in den Registern stehen (in deinem Beispiel R15,R16) an der Stelle wo ich die Register tauschen möchte könnte ich doch auch einen "rcall" machen. In der Subroutine werden die Register auch getauscht und ich komm mit ret zurück. So wie´s für mich bisher ausschaut spare ich lediglich 2 Takte (hin- und rücksprung). Oder wenn ich die Programmzeilen des Makros direkt an die Stelle schreiben würde spare ich mir halt jeweils 2 Zeilen Text... aber ist das echt schon alles? Ich dachte es gäbe noch mehr Vorteile oder so die ich noch nicht erkannt habe.... thx Danny
Um Befehle zu realisieren, die man gerne hätte, die es aber nicht gibt. Beispielsweise "branch if bit clear" auf AVR: .macro bbrc sbrs @0, @1 rjmp @2 .endmacro
Wenn du das in einer Subroutine implementierst musst du für jedes Registerpaar das du vertauschen möchtest eine eigene Subroutine schreiben. Makros sind kein Wundermittel, sie sind einfach eine sinnvolle Möglichkeit zur Abstraktion. Wer den Trick mit dem Vertauschen mit eor nicht kennt wird erst mal dumm gucken wenn er den Code ohne Makros ausgeschrieben sieht; "swap" dagegen versteht jeder.
oki, mit der eigene Routine pro Registerpaar hast du Recht. Vielleicht programmier ich auch einfach noch nicht elegant genug um soetwas öfter zu brauchen... Meist habe ich die zu verarbeitenden Bytes eh in den selben Registern (benutze immer 1 bis 4 "Standartarbeitsregister") von daher gabs bei mir noch keine Probleme das ich mehrere "gleiche" Routinen schrieben musste thx Danny
Eigentlich geht es dabei doch nur darum, Programmcode leserleicher zu gestalten. Weiterhin spart man sich mit der Verwendung eines Makro auch wieder Schreibarbeit, da der Compiler für einen das Einfügen des gesamten Marko-Codes erledigt. Man kann so auch einfacher Änderungen vornehmen, die dann im Programmcode allgemeingültig sind.
Macros haben schon ihren Sinn, solange man sie nicht wegen der Macros selbst benutzt. Ich möchte z.B. nicht auf meine PRINT-Macros verzichten müssen, die die benötigten Register vorbereiten (push), die Daten übergeben, die erforderlichen LCD-Unterprogramme aufrufen und danach die alten Registerwerte wiederherstellen. Auch das locate-Macro zur Positionierung der LCD-Ausgabe möchte ich nicht mehr missen. Mit dem Macro "swap" habe ich aber so meine Bedenken. Gibt das keine Konflikte mit dem AVR-ASM-Befehl "swap", welcher die Nibbles im Register vertauscht? (wobei ich den Algorithmus für clever halte) Der Aufruf einer Subroutine (incl. Rücksprung) dauert aber nicht 2 Takte sondern 7 Takte. In zeitkritischen Programmteilen ist es manchmal "billiger" auf kleine Unterprogramme zu verzichten und diesen Code mehrfach im Programm zu haben. ...
@HanneS: ja, mit den Takten hast natürlich recht... mal wieder geschrieben ohne zu denken :) wie gesagt, mag an meinem "uneleganten" Programmierstil liegen :-) bisher waren die zu bearbeitenden Daten immer in den entsprechenden Registern der Routine. Und ob so, oder über den Stack zu schieben ist ja "fast gleich" aber gut nachvollziehen kann ich die von euch genannte Übersichtlichkeit im Programm und die allgemeingültige Änderungsmöglichkeit thx Danny
Hier noch ein Beispiel eines Macros zur direkten 32Bit-Addition: .macro AddIL subi @0a,-@1&255 sbci @0b,-@1>>8&255 sbci @0c,-@1>>16&255 sbci @0d,-@1>>24&255 .endm Aufruf erfolgt dann einfach mit AddIL CDEF,278184 Dieses CDEF stellt 4 Register dar die ich per .def in der Macrodatei für erweiterte "Pseudobefehle" definiert habe: .def CDEFa=r18 .def CDEFb=r19 .def CDEFc=r20 .def CDEFd=r21 Im Endeffekt kann man das auch ganz normal im Code jedesmal eingeben aber mit Macros geht´s halt einfacher und übersichtlicher. MfG Andi
so :-) ich hab mir Eure Antworten mal zu Herzen genommen und mal ein Programm überarbeitet... Wenn ich das Resultat sehe ärgere ich mich das ich vorher den Wald vor lauter Bäumen nicht gesehn habe :-) diese ganzen : ldi akku, xx rcall SPI_send wirken als Makroaufruf doch erheblich übersichtlicher und eleganter Oder ChipSelect ausführen etc... Vielen Dank für die Anregungen :-) greetz Danny
Hallo alle, da hier wieder ein paar nette Makros erschienen sind, möchte ich bitten, ob diese in http://www.mikrocontroller.net/articles/AVR_Assembler_Makros eingetragen werden können oder ob die Erlaubnis zum Eintragen gegeben wird, falls keine Lust besteht es selbst zu tun ;-) Besten Dank und viele Grüße
@Thomas Burkhardt: Nur zu! Hätte allerdings ein komplett anderes Registersystem in Verbindung mit den Macros. Es gibt keine Register von R16 bis R25 und R0 bis R15 sondern A bis J und T0 bis TF. Das hat den Vorteil, das man 16Bit-Register einfach mit AB, BC oder CD, 24Bit-Register mit ABC, BCD oder CDE und 32Bit-Register mit ABCD BCDE oder CDEF angibt. Will man z. B. nach einer 16Bit-Addition mit "ADDIW AB,CD" mit dem high-Byte weiterrechnen benutzt man einfach Register B und muß nicht überlegen, welches das nun ist. Natürlich kann man weiterhin R16 etc. benutzen aber in Verbindung mit den Macros eben das oben erwähnte System. Will man eigene Registerdefinitionen machen muß man darauf achten, das bei 16 Bit ein L für low und ein H für high als letztes Zeichen steht (16BITL=r16 und 16BITH=r17) bei 32 Bit ein Buchstabe A, B, C und D (32BITA=r16, 32BITB=r17, 32BITC=r18 und 32BITD=r19). Dann kann man einfach die Macros "ADDIW 16BIT,1234" oder "ADDIL 32BIT,1234" aufrufen. Habe mir schon überlegt das in die WiKi einzutragen, ist aber ne menge Zeugs und weicht wegen dem Registersystem völlig von der Norm ab. Wenn niemand was dagegen hat, schreibe ich es rein. MfG Andi
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.