Hallo, ich habe ein kleines Programm geschrieben das die 8 Bits eines Registers nacheinander an einen Port ausgeben soll. Also R17 ist z.b. 00000001 dann soll es halt 7 mal low und 1mal high die Verzögerung erfolgt mittels Schleife. Ich habe aber ein Problem und zwar kann ich nach einen Aufruf einer Routine nicht mehr zur urspünglichen Programmstelle zurückspringen. Da die Routine ja nicht mit rcall aufgerufen wurde komme ich mit ret nicht zurück sondern lande auf init: Habe mal das asm-File mitgeschickt. Wäre klasse wenn mir jemand sagen könnte wie ich nach einem brts Aufruf wieder auf den darauf folgenden Befehl(brtc) komme.
Mit brts springst du einfach irgendwo hin und speicherst vor dem Sprung NICHT, wo du vorher warst. Hab ich das richtig verstanden? Und jetzt willst du an die vorherige Stelle zurück? Wie soll das gehen, wenn du dir das vorher nicht gespeichert hast? Folgendes könntest du stattdessen machen: brts highcall ;zum "rcall high" sprinten rcall low ;ansonsten low "callen" rjmp weiter ;low ausgeführt, nächsten befehl überspringen highcall: rcall high ;high "callen" weiter: ... In den unterprogrammen low und high benutzt du dann am Ende ret. Wenn bei "brts highcall" nicht gesprungen wurde, kannst du beim nächsten Befehl davon ausgehen, dass T nicht gesetzt ist, daher brauchst du kein zusätzliches brtc benutzen. Ganz davon abgesehen, dass man den ganzen Code viel effektiver schreiben könnte. Stell dir vor, ein Register wäre nicht nur 8 Bit sondern ganze 32 Bit breit. Würdest du dann 32 Mal fast das gleiche schreiben? Eine Anregung: Benutze eine Schleife und shifte das Register immer um 1 nach links. Das "herausgeshiftete" Bit geht nicht verloren, sondern wird im Status-Register gespeichert. An welcher Stelle genau steht dann in der ASM-Hilfe vom AVR-Studio. Viel Spass noch!
Hallo, danke für die Antwort,. Mir ist schon klar das dieser Code sehr uneffektiv ist( vor allem für mich) der Assembler macht da schon bestimmt was ordentliches draus. War auch garnicht mein Problem. Mir war ja auch klar das ret nicht funktioniert ohne rcall Aufruf. Habs einfach mal drin gelassen damit man sieht von wo ich wieder zurückwill. Deine Problemlösung hab ich ja auch schon probiert. Aber ich habe dann das gleiche Problem und zwar bewirkt dann das ret das ich hier wieder bei der Aufrufroutine lande und nicht nach auf den BRTC Befehl. Test7: bst temp2,7 ; Store bit 7 of r15 in T Flag brts recallhigh; Branch if T Flag set brtc lowhigh rcallhigh: rcall xyz xyz: xxxxx xxxxx xxxxx ret
Du hast jetzt meine Problemlösung aber nicht 1:1 übernommen. Warum willst du das T-Bit nochmal testen, auch wenn du es in deinem Unterprogramm nicht änderst? So wie du es jetzt geschrieben hast wird im Fall, dass T gesetzt ist folgendes passieren: brts rcallhigh wird anschlagen und zum befehl rcall xyz führen. Nach dem ret im Unterprogramm wird NACH "rcall xyz" fortgefahren. Im Fall, dass T NICHT gesetzt ist passiert folgendes: "brts rcallhigh" schlägt NICHT an, "brtc lowhigh" jedoch schon und an dem Punkt weiss ich nicht, was du mit dem Beispiel willst, da du nirgends lowhigh als Label deklariert hast ;) Hier nochmal mein Beispiel: brts highcall ;zum "rcall high" sprinten rcall low ;ansonsten low "callen" rjmp weiter ;low ausgeführt, nächsten befehl überspringen highcall: rcall high ;high "callen" weiter: ... Beim ersten Befehl wird geprüft ob T geseztzt ist. Wenn ja, dann wird zu highcall gesprungen und dort wird mit rcall zu high gesprungen. Ist das Unterprogramm "high" fertig, geht es nach dem rcall weiter, also dort wo das Label "weiter" deklariert ist. Im Fall, dass T nicht gesetzt ist, wird beim ersten Befehl nicht gesprungen. An dieser Stelle wissen wir, dass wir nicht gesprungen sind, also dass T nicht gesetzt ist. Daher rufen wir "low" mit rcall auf. Wenn "low" fertig ist und "ret" benutzt gehts nach dem rcall weiter, also beim dritten Befehl, nämlich "rjmp weiter". Dieser Befehl ist dazu gut, da ansonsten der nächste Befehl wieder "rcall high" wäre, aber das wollen wir ja nicht, daher überspringen wir diesen Aufruf quasi. Ich hoffe, du verstehst jetzt die Funktionsweise.
Hallo, ok jetzt hab ichs verstanden. Werde das jetzt ausprobieren, danke nochmal.
und der Assembler macht gar nichts dran, der übersetzt es so wie es da steht (wenn er es kann) - selbstständige Optimierungen gibts da nicht.
Stimmt. Der Assembler macht aus jedem Befehl exakt einen Maschinenbefehl. Ob diese logisch angeordnet sind, ist Sache des Programmierers. Um das zu ergründen, ist die Simulation im AVR-Studio sehr gut geeignet. Besonders bei solch kleinen Programmen kann man per Einzelschritt logische Fehler sehr schnell aufspüren. Dabei sollte man sich im Workspace (linke Seite) das Statusregister und die benutzten I/Os anzeigen lassen und im Memory-Fenster (unten rechts) den Inhalt der Register. Und die F11-Taste sollte man erst wieder betätigen, wenn man vorhersagen kann, was als nächstes passieren wird. Passiert das Vorhergesagte, dann ist es gut, passiert etwas Anderes, dann hat man irgendwo einen Denkfehler gemacht. Dann hilft die Hilfe zu den ASM-Befehlen weiter. Übrigens ist ein Programmablaufplan (Papier & Bleistift) recht hilfreich, solche logischen Fehler wie im vorgestellten Programm zu erkennen. Gruß... ...HanneS...
Hallo, ok danke, war also ne Fehlannahme von mir das ja was beim Assamblieren optimiert wird. Vielleicht ist es bei x86er Assembler so. Dachte das mal irgendwo gelesen zu haben.
Kein ASM-Compiler optimiert oder verändert irgend was an den Maschinen-Befehlen. Das machen nur C-Compiler oder andere Hochsprachen aber in der logischen Abfolge verändert keiner was. BRTS und BRTC prüfen einfach ob das T-Bit in SREG gesetzt (1) oder gelöscht (0) ist und verzweigen (springen) dann zu ner anderen Stelle wenn die Prüfung zutrifft. In Deinem Fall mit einem Aufruf eines Unterprogrammes wenn T-Bit gesetzt oder gelöscht ist mußt Du anders rum denken. BRTC nohigh1 ;Ist Zustand (T-Bit) low (0)? rcall high ;Wenn nicht, also high, dann zu high callen. nohigh1: BRTS nolow1 ;Ist Zustand (T-Bit) high (1)? rcall low ;Wenn nicht, also low, dann zu low callen. nolow1: ..... Man überspringt durch das Prüfen des Gegenteiles den RCALL. geht auch ohne dem T-Bit sofern das Register mit dem zu prüfenden Bit eines von R16 - R31 ist. Mit SBRS Rr,n und SBRC Rr,n (Skip if Bit in Register is Set/Clear) überspringt man den nächsten Befehl wenn eine Bit-Prüfung zutrifft. SBRC temp2,6 ;Ist Bit 6 low (0)? ;Wenn ja, dann RCALL überspringen. rcall high ;Wenn nicht, also high, dann zu high callen. SBRS temp2,6 ;Ist Bit 6 high (1)? ;Wenn ja, dann RCALL überspringen. rcall low ;Wenn nicht, also low, dann zu low callen. ..... Mit SBRS und SBRC erspart man sich die zusätzlichen Marken im Prog. Gruß Andi
Es gibt keine ASM-Compiler, das sind Assembler (im Gegensatz zu Hochsprachen-Compilern)... Das Einsparen von Marken / Labels bringt nix, da diese keine Ressourcen verbrauchen. Sie dienen nur dazu, einen (bedingten) relativen Sprung zu berechnen. Im eigentlichen Maschinensprachebefehl steht dann nur die Sprungdifferenz, die zum PC (Programm-Counter) addiert wird. ...HanneS...
Das ein Label keine Resourcen braucht ist schon klar. Sollte nur verdeutlichen, das SBRS und SBRC den nächsten Befehl nach zutreffender Bit-Prüfung sowieso überspringen. Das mit dem "ASM-Compiler" ist halt in vieler Munde obwohl es das nicht ist und irgend wie auch zu mir rübergerutscht. Es wird Assembliert (gebaut, erstellt) und nicht Compiliert (umgewandelt). Man, Du mußt aber auch alles zerlegen. Gruß Andi
Hi Andi... Ach so, ist wohl so wie mit der "String-Taste" am PC... ;-)) Mach dir nix draus, nimms mit Humor, mach ich doch auch immer, auch wenns manchmal nicht so aussieht. Beste Grüße... ...HanneS...
Dann muß ich meinen Senf aber auch dazu geben :-) Marken bzw. Labels verbrauchen sehr wohl Resourcen, zwar nicht im Programmspeicher der µc, aber in der Symboltabelle des Assemblers und machen diese ggf. unnötig groß und unübersichtlich.
das stört den assembler aber herzlich wenig wenn er nun 20 symbole mehr zu verarbeiten hat oder nicht. übersichtlichkeit kennen computer nun auch noch nicht - so weit ist die ki forschung noch nicht :) und auf einem aktuellen pc dürfte das irgendwo im kaum messbaren bereich länger dauern
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.