Forum: Mikrocontroller und Digitale Elektronik Rückkehr nach Befehl BRTS o. BRTC?


von Thomas O. (Gast)


Lesenswert?

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.

von Thomas O. (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

ups hab das ams-File vergessen

von Christof Krüger (Gast)


Lesenswert?

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!

von Thomas O. (Gast)


Lesenswert?

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

von Christof Krüger (Gast)


Lesenswert?

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.

von Thomas O. (Gast)


Lesenswert?

Hallo,

ok jetzt hab ichs verstanden. Werde das jetzt ausprobieren, danke
nochmal.

von crazy horse (Gast)


Lesenswert?

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.

von ...HanneS... (Gast)


Lesenswert?

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

von Thomas O. (Gast)


Lesenswert?

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.

von Andi (Gast)


Lesenswert?

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

von ...HanneS... (Gast)


Lesenswert?

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

von Andi (Gast)


Lesenswert?

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

von ...HanneS... (Gast)


Lesenswert?

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

von m.merten (Gast)


Lesenswert?

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.

von Tobi (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.