Bascom gesetzte Flags auf True/false prüfen und enstprechende Subroutinen ausführen

muellerjm

Neues Mitglied
28. Juli 2011
12
0
0
61
Sprachen
Hallo,


Ich möchte die gesetzen Bits einer Variablen püfen und dann die dafür angelegten Subroutinen ausführen. Muss ich hier if-then-else kaskadieren, oder gibt es wie zb. in PHP mit 'continue' eine Mögichkeit, das ein Schleife weiter ausgeführt wird obwohl die Bedingung bereits erfüllt ist? Oder ich habe in den ganzen Befehlen etwas nicht gesehen....

Danke
Joachim
 
Hallo Joachim,
ich verstehe deinen Post leider nicht. Was meinst du mit der "continue" Möglichkeit aus PHP (ich kenne mich mit PHP nicht aus)?
Zeig doch mal ein wenig Code, wie du dir das vorstelltst.

Grüße

Sebastian
 
Hallo,

nur zur Darstellung. Wenn das erste Case erfüllt ist, soll die Schleife trotzem noch die anderen Casebedinguen prüfen. D.h. wenn x Case true sind, dann sollen auch x gosub ausgeführt werden. Ich will z.b. die Flags eines Bytes prüfen 00010100. Wenn Bit 2 und Bit 4 true sind ist dann Routine 2 und 4 ausführen

nur zur Darstellung.
select case test
case 1: gosub Routine_1
(in PHP gibts an dieser Stelle 'continue')
case 2: gosub_Routine_2
end select

Joachim
 
Hallo Joachim,
da bleiben dir wohl nur die einzelnen Abfragen der Bits:
If Test.0 = 1 Then Gosub Routine_0
If Test.1 = 1 Then Gosub Routine_1
...

Ein Select würde hier ja schon deshalb nicht funktionieren, weil du den Wert der Variablen Test ja nicht direkt abfragen kannst.
Select Case Test fragt den Gesamtwert ab, nicht die einzelnen Bits.

Grüße

Sebastian
 
Hallo Joachim,

dein Problem läßt sich sehr effektiv in Assembler lösen. Ganz besonders dann, wenn du keine Parameter an das Unterprogramm übergeben willst.
Könntest du dich damit anfreunden?

Grüße
Werner
 
Boahh.. ich würde mir das gerne mal anschauen, evtl. komme ich zurecht. Ich bin derzeit über einen größeren Ethernetprojekt. Da schlage ich mich schon exzessiv mit Javascript, Mysql und PHP rum. Elektronikkenntnisse vertiefe ich auch noch nebenbei. aber für jede Info immer dankbar.

Joachim
 
Hallo Joachim,

was dir der Bastian geschrieben hat, ist schon eine übersichtliche Lösung. Ob's mit Maschinensprache schneller/"besser" geht, kann ich nicht sagen - kommt darauf an, wie Bastian's Lösung vom Bascom-Compiler umgesetzt wird.

Die (oder besser EINE) Lösung in Assembler zeichnet sich allerdings durch eine "gewisse Eleganz und Allgemeingültigkeit" aus.

Praktisch jeder Prozessor, also auch der AVR, besitzt Befehle zum Verschieben der Bits innerhalb eines Registers um eine Position. Beim AVR heißt der Befehl "ROR" (ROtate (through Carry) Right) für eine Position nach rechts und "ROL" (ROtate (through Carry) Left) für die Verschiebung um eine Position nach links. Praktisch wird im ersten Fall der Wert im Register halbiert, im zweiten Fall verdoppelt. Was man allerdings noch zu beachten hat, ist, dass z.B. beim Rechtsschieben das unterste Bit ja "herausfällt" (ähnliches gilt beim Linksschieben). Um diesen "Übertrag" zu berücksichtigen, hat der Prozessor ein sogenanntes Übertragsbit (neudeutsch: Carryflag) im Statusregister. Falls also das unterste Bit gesetzt war, ist es nach dem "rotieren" im Carryflag gelandet.

Den Zustand des Statusregisters kann man natürlich abfragen und entsprechend den Flags Verzweigen (auf neudeutsch: conditional branches). Die Sprungbefehle, die hioer relevant sind, betreffen natürlich das Carry-Flag:
BRCC = BRanch Carry Clear (=verzweige bei gelöschtem Carry Flag) und
BRCS = BRanch Carry Set (=verzweige bei gesetztem Carry Flag).

Genau das können wir ausnutzen. Dein Code könnte also folgendermaßen aussehen:

Code:
LDS   R1,{Test}   ' (Byte-)Variable Test in's Register "R1" laden

ROR   R1          ' unterstes Bit in's Carry schieben 
BRCC  CheckBit1   ' Sprung, falls nicht gesetzt
PUSH  R1          ' aktuellen Wert (Test DIV 2) merken
CALL  RoutineBit0 ' Routine für gesetztes Bit "0" aufrufen
POP   R1          ' gemerkten Wert zurückholen und

CheckBit1:        ' mit nächstem Bit weiter machen
ROR   R1
BRCC  CheckBit2
PUSH  R1
CALL  RoutineBit1
POP   R1

......

'.....................................................................
RoutineBit0:

......

RETURN
'.....................................................................
RoutineBit1:

......

RETURN
'.....................................................................

Die zugehörigen Unterprogramme brauchst du auch nicht irgendwie deklarieren - die Angabe eines Labels reicht völlig. Abschließen mußt du es mit einem "RETURN" (der Maschinensprachebefehl "CALL" ist identisch zum Basic-"GOSUB").

Grüße
Werner
 
Hi Werner,

Den Zustand des Statusregisters kann man natürlich abfragen und entsprechend den Flags Verzweigen (auf neudeutsch: conditional branches). Die Sprungbefehle, die hioer relevant sind, betreffen natürlich das Carry-Flag:
BRCC = BRanch Carry Clear (=verzweige bei gelöschtem Carry Flag) und
BRCS = BRanch Carry Set (=verzweige bei gesetztem Carry Flag).

Genau das können wir ausnutzen. Dein Code könnte also folgendermaßen aussehen:

Code:
LDS   R1,{Test}   ' (Byte-)Variable Test in's Register "R1" laden

ROR   R1          ' unterstes Bit in's Carry schieben 
BRCC  CheckBit1   ' Sprung, falls nicht gesetzt
PUSH  R1          ' aktuellen Wert (Test DIV 2) merken
CALL  RoutineBit0 ' Routine für gesetztes Bit "0" aufrufen
POP   R1          ' gemerkten Wert zurückholen und

CheckBit1:        ' mit nächstem Bit weiter machen
ROR   R1
BRCC  CheckBit2
PUSH  R1
CALL  RoutineBit1
POP   R1
es geht beim AVR sogar noch eleganter und ohne das Push/Pob des Registers mit dem Flag. Außerdem müßtest du vor dem Sprung in das Unterprogramm ja auch noch das Carry sichern weil es ja sozusagen das 9te Bit in deinem Ringschieberegister ist. Es könnte durch Befehle im Unterprogramm verändert werden und vernichtet damit eigentlich ja deinen Inhalt des Registers mit den 8 Flagbits.

Ich würde es folgendermaßen machen ...
Code:
SBRC   R1, 0
CALL RoutineBit0
SBRC   R1, 1
CALL RoutineBit1
SBRC   R1, 2
CALL RoutineBit2
...
..
.

RoutineBit0:
...
RETURN
RoutineBit1:
...
RETURN
...
..
.
Damit spart man sich das Push/Pop, verbraucht weniger Stack, mußt nicht aufs Carry aufpassen und wenn man das Register R1 in den Subroutinen nicht anfaßt dann ist diese Lösung sehr elegant, kurz und Resourcenschonend ;)

Mit SBRC (Skip If Bit in Register is Cleared) überspring man bei einer 0 auf der entsprechenden Bitposition in R1 einfach den zugehörigen nachfolgenden Call-Befehl.

Gruß
Dino
 
Hallo Dino,

Einspruch, Euer Ehren *lol*.

HTML:
Haarspalterei ON
1.) Die "multiple Carryabfrage" benötigt genau 1 Byte Platz auf dem Stack (ohne den Funktionsaufruf), dafür kann man in der aufgerufenen Routine lustig mit Basic weitermachen, ohne sich um "Register zu kümmern"
2.) Das Speichern des Carryflags ist nicht notwendig, da die Bitauswertung ja schon erfolgt ist und die zuständige Unterroutine ausgewählt wurde.
3.) Die "Universalität" beruht darauf, dass praktisch jeder Prozessor (auf dem PC z.B. hieße "ROR" ebenfalls "ROR" und "BRCC" "JNC") die entsprechenden Befehle kennt und weil
3a.) man beim Kopieren der Befehlszeilen nur die beiden Labels anpassen muß, während man in deiner Version auch noch das Bitmuster anpassen muß ;).
4.) Dass deine Routine ein Byte pro Auswertung kürzer ist, fällt bei der Größe des Flash in der Regel nicht in's Gewicht :p
HTML:
Haarspalterei OFF

Viele Grüße
Werner :wink:
 
Hi Werner,

4.) Dass deine Routine ein Byte pro Auswertung kürzer ist, fällt bei der Größe des Flash in der Regel nicht in's Gewicht :p
Beim Flash fällt es nicht weiter auf. Beim Verbrauch von Taktzyklen bei der Abarbeitung aber schon wenn man zeitkritische Anwendungen hat ;) Ätsch :p

Gruß
Dino
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)